日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

文巾解题 15. 三数之和

發布時間:2025/4/5 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 文巾解题 15. 三数之和 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 題目描述

2 解題思路

2.1 使用兩數之和函數

這種做法目前超時了,如果大家有想到合適的減時間/剪枝的方法,歡迎私信or評論~

兩數之和的方法見文巾解題 1. 兩數之和_劉文巾的博客-CSDN博客

我的思路是這樣的,先固定一個數x,然后另外兩個數就需要和為-x,那么兩數之和為-x就可以調用之前的函數。

不過唯一不同的是,之前的“兩數之和”,只要求出一組解就可以了,但我們這里需要的是全部解。

所以我對“兩數之和”中的函數進行了一點改造。當我們找到滿足條件的兩個數時,我不直接返回。而是將這組解放到一個list中。等所有的元素都遍歷完了,所有滿足條件的解都放到這個list中了。那么把這個list返回,就是和等于這個-x的所有數對了。

?

然后我們對每一個數對,將x拼接進去。得到一組滿足條件的“三數組合”。

?

但這時候“三數組合”會有冗余的。我們需要去重。我現在的思路是,將“三數組合”排序,然后轉換成元組tuple,之后使用set(list不能應用于set上,tuple可以)

class Solution:def twoSum(self, nums: List[int], target: int) -> List[int]:ret=[]for i in range(len(nums)):x=nums[i]y=target-xif(y in nums):if(i==nums.index(y)):continueelse:ret.append([x,y])return(ret) #文巾解題1 兩數之和代碼 稍作改動def threeSum(self, nums: List[int]) -> List[List[int]]:ret=[]l=len(nums)s=set(nums) #不同的“和”for i in s:tmp=self.twoSum(nums[0:nums.index(i)]+nums[nums.index(i)+1:l],-i) #找所有滿足條件的“兩數組合”if(tmp==[]):continueelse:for j in tmp:j.extend([i])j.sort()ret.append(tuple(j)) #所有滿足條件的“三數組合” return (list(set(ret))) #結果去重

2.2 排序 + 雙指針(leetcode方法)

題目中要求找到所有不重復且和為 0 的三元組,這個不重復的要求使得我們無法簡單地使用三重循環枚舉所有的三元組。

這是因為在最壞的情況下,數組中的元素全部為 0。任意一個三元組的和都為 0。如果我們直接使用三重循環枚舉三元組,會得到 O(N^3)個滿足題目要求的三元組(其中 N?是數組的長度)時間復雜度至少為 O(N^3)。在這之后,我們還需要使用哈希表進行去重操作,得到不包含重復三元組的最終答案,又消耗了大量的空間。這個做法的時間復雜度和空間復雜度都很高,因此我們要換一種思路來考慮這個問題。

?

不重復的本質是什么?我們保持三重循環的大框架不變,只需要保證:

第二重循環枚舉到的元素不小于當前第一重循環枚舉到的元素;

第三重循環枚舉到的元素不小于當前第二重循環枚舉到的元素。

?

也就是說,我們枚舉的三元組 (a, b, c)滿足 a≤b≤c,保證了只有 (a, b, c) 這個順序會被枚舉到,而 (b, a, c)、(c, b, a)等等這些不會,這樣就減少了重復。

要實現這一點,我們可以將數組中的元素從小到大進行排序,隨后使用普通的三重循環就可以滿足上面的要求。

?

同時,對于每一重循環而言,相鄰兩次枚舉的元素不能相同,否則也會造成重復。

舉個例子,如果排完序的數組為[0, 1, 2, 2, 2, 3]。

我們使用三重循環枚舉到的第一個三元組為 (0, 1, 2),如果第三重循環繼續枚舉下一個元素,那么仍然是三元組 (0, 1, 2),產生了重復。

因此我們需要將第三重循環「跳到」下一個不相同的元素,即數組中的最后一個元素 3,枚舉三元組 (0, 1, 3)。

?

下面給出了改進的方法的偽代碼實現:

nums.sort()
for first = 0 .. n-1
? ? // 只有和上一次枚舉的元素不相同,我們才會進行枚舉
? ? if first == 0 or nums[first] != nums[first-1] then
? ? ? ? for second = first+1 .. n-1
? ? ? ? ? ? if second == first+1 or nums[second] != nums[second-1] then
? ? ? ? ? ? ? ? for third = second+1 .. n-1
? ? ? ? ? ? ? ? ? ? if third == second+1 or nums[third] != nums[third-1] then
? ? ? ? ? ? ? ? ? ? ? ? // 判斷是否有 a+b+c==0
? ? ? ? ? ? ? ? ? ? ? ? check(first, second, third)

這種方法的時間復雜度仍然為 O(N^3),畢竟我們還是沒有跳出三重循環的大框架。

然而它是很容易繼續優化的,可以發現,如果我們固定了前兩重循環枚舉到的元素 a 和 b,那么只有唯一的 c 滿足 a+b+c=0。當第二重循環往后枚舉一個元素 b'時,由于 b' > b,那么滿a+b'+c'=0的 c'?一定有 c' < c,即 c'在數組中一定出現在 c?的左側。也就是說,我們可以從小到大枚舉 b,同時從大到小枚舉 c,即第二重循環和第三重循環實際上是并列的關系。(那么前面為代碼中c右側的遍歷部分就被剪枝剪掉了)

有了這樣的發現,我們就可以保持第二重循環不變,而將第三重循環變成一個從數組最右端開始向左移動的指針,從而得到下面的偽代碼(加粗的部分為兩者不同之處):

nums.sort()
for first = 0 .. n-1

? // 只有和上一次枚舉的元素不相同,我們才會進行枚舉
? ? if first == 0 or nums[first] != nums[first-1] then
? ? ? ? // 第三重循環對應的指針
? ? ? ? third = n-1

? ? ? ? for second = first+1 .. n-1
? ? ? ? ? ? if second == first+1 or nums[second] != nums[second-1] then
? ? ? ? ? ? ? ? // 向左移動指針,直到 a+b+c 不大于 0
? ? ? ? ? ? ? ? while nums[first]+nums[second]+nums[third] > 0
? ? ? ? ? ? ? ? ? ? third = third-1

? ? ? ? ? ? ? ? // 判斷是否有 a+b+c==0
? ? ? ? ? ? ? ? check(first, second, third)

這個方法就是我們常說的「雙指針」。

當我們需要枚舉數組中的兩個元素時,如果我們發現隨著第一個元素的遞增,第二個元素是遞減的,那么就可以使用雙指針的方法,將枚舉的時間復雜度從 O(N^2)減少至 O(N)。

為什么時間復雜度是 O(N) 呢?這是因為在枚舉的過程每一步中,「左指針」會向右移動一個位置(也就是題目中的 bb),而「右指針」會向左移動若干個位置,這個與數組的元素有關,但我們知道它一共會移動的位置數為O(N)。

均攤下來,每次也向左移動一個位置,因此時間復雜度為 O(N)。

class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:n = len(nums)nums.sort()#對nums進行排序ans = list()# 枚舉 afor first in range(n):# 需要和上一次枚舉的數不相同if first > 0 and nums[first] == nums[first - 1]:continue#third 對應的指針初始指向數組的最右端third = n - 1target = -nums[first]#second和third指針指向的元素和為first指針指向的元素的相反數# 枚舉 bfor second in range(first + 1, n):# 需要和上一次枚舉的數不相同if second > first + 1 and nums[second] == nums[second - 1]:continue# c向左移動的時候,需要保證 b 的指針在 c 的指針的左側while second < third and nums[second] + nums[third] > target:third -= 1# 如果指針重合,隨著 b 后續的增加# 就不會有滿足 a+b+c=0 并且 b<c 的 c 了,可以退出循環if second == third:breakif nums[second] + nums[third] == target:ans.append([nums[first], nums[second], nums[third]])return ans

?

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的文巾解题 15. 三数之和的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩福利在线播放 | 法国伦理少妇愉情 | 国产做爰免费观看视频 | 中文无码精品一区二区三区 | 免费成人美女在线观看. | 风韵丰满熟妇啪啪区老熟熟女 | 久久久久久电影 | 午夜h | 可以看的av网站 | 国产黑丝在线视频 | 亚洲精品鲁一鲁一区二区三区 | 免费av看片| 清纯唯美第一页 | 欧美一区二区日韩 | 成人涩涩网| 国产95在线 | 国产综合视频在线观看 | 99精品欧美一区二区蜜桃免费 | 成人免费在线网站 | 国产精品sm| av毛片一区 | 久久久久人妻一区二区三区 | 男人激烈吮乳吃奶爽文 | 日韩精品一区二区不卡 | 日韩一级在线观看视频 | 成人精品免费在线观看 | 美女91网站 | 女同另类之国产女同 | 日韩免费在线观看 | 成人在线网 | 一区二区三区四区在线观看视频 | 性爱免费视频 | 主播一区二区 | 五月在线 | 欧美男女啪啪 | 艳妇乳肉豪妇荡乳av无码福利 | 五月婷婷丁香久久 | 成人午夜精品 | 亚洲色图偷拍视频 | 91视频在线观看视频 | 国产日产欧美一区二区 | 亚洲熟乱| 日韩精品伦理 | 毛片a| 天天综合网永久 | 亚洲欧美韩国 | 国产www| 野外吮她的花蒂高h在线观看 | 日韩城人免费 | 性欧美1819性猛交 | 久久久久久麻豆 | 亚洲av无码久久精品狠狠爱浪潮 | av天天堂| 一区二区欧美在线 | 中文字幕在线观看免费高清 | 黄视频在线免费 | 91大神视频在线播放 | 五月婷婷狠狠干 | 国产欧美一区二区精品性色超碰 | 久久久久久久久福利 | 男操女视频在线观看 | 欧美性免费 | 在线观看福利网站 | 在线免费你懂的 | 国产精品 欧美激情 | 成人午夜又粗又硬又大 | 国产99在线 | 日韩免费网站 | 午夜在线观看视频18 | 天狂传说之巴啦啦小魔仙 | 亚洲淫欲 | 最新色网址 | 一起操在线观看 | 色先锋av | 91精品国产综合久久久蜜臀 | 综合一区在线 | 天天干夜夜草 | 中国av在线 | 国产日韩欧美91 | 亚洲免费成人网 | 天天天天操 | 色播五月激情五月 | 电影桑叶2在线播放完整版 222aaa | 尤物在线精品 | 欧美成本人视频 | 三级中文字幕在线 | 国产一区二区精品在线观看 | 国产麻豆免费观看 | 免费a在线观看播放 | av日韩一区二区 | 久久免费一级片 | 日韩三级免费看 | 久久综合婷婷国产二区高清 | 成人乱人乱一区二区三区一级视频 | 天天色天天色 | 国产成人精品无码免费看夜聊软件 | 九九九在线视频 | 91偷拍富婆spa盗摄在线 | 无码精品人妻一区二区 |