題目描述
這是 LeetCode 上的 15. 三數之和 ,難度為 中等。
Tag : 「雙指針」、「排序」、「n 數之和」
給你一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?
請你找出所有和為 0 且不重複的三元組。
注意:答案中不可以包含重複的三元組。
示例 1:
輸入:nums = [-1,0,1,2,-1,-4]
輸出:[[-1,-1,2],[-1,0,1]]
示例 2:
輸入:nums = []
輸出:[]
示例 3:
輸入:nums = [0]
輸出:[]
提示:
- 0 <= nums.length <= 3000
- -<= nums[i] <=
排序 + 雙指針
對數組進行排序,使用三個指針
i
、
j
和
k
分别代表要找的三個數。
- 通過枚舉
确定第一個數,另外兩個指針 i
,j
分别從左邊 k
和右邊 i + 1
往中間移動,找到滿足 n - 1
的所有組合。nums[i] + nums[j] + nums[k] == 0
-
和 j
指針的移動邏輯,分情況讨論 k
:sum = nums[i] + nums[j] + nums[k]
-
> 0:sum
左移,使k
變小sum
-
< 0:sum
右移,使j
變大sum
-
= 0:找到符合要求的答案,存起來sum
由于題目要求答案不能包含重複的三元組,是以在确定第一個數和第二個數的時候,要跳過數值一樣的下标(在三數之和确定的情況下,確定第一個數和第二個數不會重複,即可保證三元組不重複)。
代碼:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
int n = nums.length;
List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < n; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int j = i + 1, k = n - 1;
while (j < k) {
while (j > i + 1 && j < n && nums[j] == nums[j - 1]) j++;
if (j >= k) break;
int sum = nums[i] + nums[j] + nums[k];
if (sum == 0) {
ans.add(Arrays.asList(nums[i], nums[j], nums[k]));
j++;
} else if (sum > 0) {
k--;
} else if (sum < 0) {
j++;
}
}
}
return ans;
}
}
- 時間複雜度:排序的複雜度為,對于每個
而言,最壞的情況i
和j
都要掃描一遍數組的剩餘部分,複雜度為。整體複雜度為k
- 空間複雜度:
最後
這是我們「刷穿 LeetCode」系列文章的第
No.15
篇,系列開始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道題目,部分是有鎖題,我們将先将所有不帶鎖的題目刷完。