題目
給你一個包含 n 個整數的數組 nums
,判斷 nums
中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?請你找出所有滿足條件且不重複的三元組。
注意:答案中不可以包含重複的三元組。
示例:
給定數組 nums = [-1, 0, 1, 2, -1, -4],
滿足要求的三元組集合爲:
[
[-1, 0, 1],
[-1, -1, 2]
]
解題思路
算法步驟:
1)首先對數組進行排序。
2)遍歷排序後數組:
- 2.1)若 nums[first]>0,因爲已經排序好,所以後面不可能有三個數之和等於 0,直接返回結果。
- 2.2)對於nums[first]的重複元素跳過,避免出現重複解。
- 2.3)令左指針 second=first+1,右指針 third=n-1,當 second<third 時,執行循環:
- 2.3.1)若和小於 0,說明 nums[second]太小,second 右移;
- 2.3.2)若和大於 0,說明 nums[third]太大,third 左移;
- 2.3.3)當和等於0,找到一個解,添加到結果中,同時將 second 右移, third 左移,判斷新的左界及右界是否和上一位置重複,去除重複解。
複雜度分析:
時間複雜度:O(n^2),數組排序 O(nlogn),遍歷數組 O(n),雙指針遍歷 O(n),總體 O(nlogn)+O(n)∗O(n) = O(n^2)
空間複雜度:O(logn),排序的空間複雜度爲 O(logn)。
代碼
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int n = nums.length;
List<List<Integer>> res = new ArrayList<>();
// 先排序
Arrays.sort(nums);
for(int first=0; first<n; first++){
// 後面不可能有三個數加和等於 0,直接返回結果
if(nums[first]>0){
return res;
}
// 如果和上一個數相同,就跳過
if(first>0 && nums[first]==nums[first-1]){
continue;
}
int second = first+1;
int third = n-1;
while(second<third){
int sum = nums[first] + nums[second] + nums[third];
if(sum<0){
second++;
}else if(sum>0){
third--;
}else{
List<Integer> list = new ArrayList<>();
list.add(nums[first]);
list.add(nums[second]);
list.add(nums[third]);
res.add(list);
second++;
third--;
// 如果和上一個數相同,就跳過
while(second<third && nums[second]==nums[second-1]){
second++;
}
// 如果和上一個數相同,就跳過
while(second<third && nums[third]==nums[third+1]){
third--;
}
}
}
}
return res;
}
}