這道題與two sum很像,我們很容易想到利用two sum的程式來解答這個問題,對於a+b+c = 0,有-c = a+b,這相當於target設定為-c的two sum問題。區別在於,a和b的值不是唯一的,即這個two sum的答案不唯一。
除了找到所有正確的a和b外,還要解決三元組重複的問題。
我們依然考慮在two sum的基礎上解決這個問題。
首先,two sum的核心**是:
for
(int i =
0; i < nums.
size()
;++i)
; m[nums[i]
]= i;
}
我們把return
那一行做一些修改,改為新增乙個三元組到答案中,就可以作為本題的核心**了。
問題在於,這樣做會導致大量重複的三元組,有兩種情況的重複:
調換元素順序導致的重複:如[-1,0,1]和[0,-1,1]本質上是同乙個三元組
不同元素的值相同導致的重複:如nums=[-4,2,2,2],會導致兩個[-4,2,2]的產生;nums=[-1,-1,0,1],會導致兩個[-1,0,1]的產生
情況1比較容易解決,我們在新增三元組時,只新增a <= b <= c這樣的[a,b,c]到答案中,即指定答案中三元組的順序。
但這樣做是不夠的,不僅解決不了情況2,當多個元素值相同時,連情況1也解決不了。如nums=[0,0,0],這時滿足a == b == c,我們加的限制條件也就沒有用了。
採用排序的方法能夠很好地解決這兩種情況的重複。
對於排序之後的陣列,我們使用雙層迴圈,外層迴圈用於尋找target值,內層迴圈的邏輯就是two sum的邏輯,借助雜湊表來尋找sum為target的兩個元素。
我們保證內層迴圈列舉到的元素不小於外層迴圈的元素,就可以解決情況1。對於每重迴圈還要保證相鄰兩次遍歷到的元素值不相同,這是為了解決情況2。偽**如下:
nums.
sort()
for i =0..
.n-1
if i >
0&& nums[i]
== nums[i-1]
continue
;for j = i+1..
.n-1
if j > i+
1&& nums[j]
== nums[j-1]
continue
;// a=nums[j], 用雜湊表找對應的b
需要注意的是,如果我們像two sum中那樣一邊遍歷一邊向雜湊表中插入元素,可以滿足a <= b <= c,即解決情況1。因為在遍歷到b時target-b還不在雜湊表中,而遍歷到c時target-c在雜湊表中。
這樣做貌似效率很高,但會錯過[-4,2,2]這樣的三元組。因為當j == 1時nums[j]不在雜湊表中,而j=2時又因為nums[j] == nums[j-1],不會參與判斷。我們為了去除重複結果矯枉過正了。解決辦法是在排序之後先將陣列元素插入雜湊表中。
我們增加了乙個判斷條件m[sum - nums[j]] > j
來保證a <= b <= c。對於[-4,2,2]這種元素有相同值的情況,也是滿足的,因為經過排序後最終覆蓋雜湊表的肯定是index最大的那個元素。最終,我們要新增的三元組是[nums[i], nums[j], nums[m[target - nums[j]]]]
。
**
class solution );
}}}return result;}}
;
複雜度分析
時間複雜度o(n
2)
o(n^2)
o(n2
),空間複雜度o(n
)o(n)
o(n)
。注意用的排序演算法時間複雜度o(n
logn
)o(nlogn)
o(nlog
n)。去除重複三元組的思路與解法一相同,但我們不使用雜湊表,而是使用雙指標來優化暴力解法。
暴力解法是3重迴圈,同時滿足兩個條件:
內層遍歷迴圈元素不小於外層迴圈遍歷的元素
對於每一重迴圈,相鄰遍歷的元素值不相同
即解法一中的核心想法。
3重迴圈獲取到a,b,c,如果a+b+c = 0,它們就是乙個滿足條件的三元組。自然,a,b對應唯一的c,當b增大時,c減小,因此,我們可以在從左往右列舉b的同時從右往左列舉c。
當a+b+c > 0時,把右指標向左移動,取更小的c
當a+b+c = 0時,把左指標向右移動,取更大的b,此時肯定有a+b+c > 0
當a+b+c < 0時,可以確定這個a,b沒有對應的c,把左指標向右移動,取更大的b。是否要把右指標向右移動呢?不用。首先要明白為什麼會有a+b+c < 0出現,肯定因為1.導致的,如果我們又把右指標往右移,那麼又會得到a+b+c > 0的結果,最終還得把右指標移到現在這位置來
這樣一來,就可以把第二重和第三重迴圈壓縮成乙個迴圈了。當然,始終要保證b <= c,否則退出迴圈。
**
class solution );
}}}return result;}}
;
複雜度分析
時間複雜度o(n
2)
o(n^2)
o(n2
),空間複雜度o(l
ogn)
o(logn)
o(logn
),排序的空間複雜度為o(l
ogn)
o(logn)
o(logn
)。
LeetCode第15題解析
給你乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c 使得 a b c 0 請你找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組。示例 給定陣列 nums 1,0,1,2,1,4 滿足要求的三元組集合為 1,0,1 1,1,2 class so...
LeetCode第3題題解 無重複字元的最長子串
題目 leetcode 題目描述 給定乙個字串,請你找出其中不含有重複字元的最長子串的長度。示例 1 輸入 abcabcbb 輸出 3 解釋 因為無重複字元的最長子串是 abc 所以其長度為 3。示例 2 輸入 bbbbb 輸出 1 解釋 因為無重複字元的最長子串是 b 所以其長度為 1。示例 3 ...
LeetCode第15題 三數之和
給定乙個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c 使得 a b c 0 找出所有滿足條件且不重複的三元組。注意 答案中不可以包含重複的三元組。例如,給定陣列 nums 1,0,1,2,1,4 滿足要求的三元組集合為 1,0,1 1,1,2 思路 首先想到的肯定...