LeetCode笔记汇总
题目
给你一个包含 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
-10^5 <= nums[i] <= 10^5
思路
先考虑特殊情况:nums为空或长度小于三,此时直接返回空的list即可
本题若采用暴力列举法,时间复杂度至少为N^3,况且之后还需要通过hash表来去重,因此排除。
若先将nums排序,则这道问题就会变得简单很多:已知一个有序数组,求其中任意三项和为定值的情况。
再将问题进一步细分:从左边开始定义一个指针i,求出目标值与nums[i]的差值sum=0-nums[i],在数组剩余的部分中,找两个和为sum的项。其中需要处理好left和right指针的增减,并注意避免空指针异常。
当一轮遍历结束后,指针i向左移动一位,此时需要判断两个条件:1.nums[i]的值是否大于0,因为已经排过序,若nums[i]>0则必定没有结果(剪枝)。2.nums[i]的值与nums[i-1]的值是否相同,若相同则属于重复,需去除
代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList();
if(nums.length < 3 || nums ==null) return ans;
int left,right,sum;
Arrays.sort(nums);
for(int i = 0;i < nums.length;i++){
if(nums[i] > 0) break;
//从第二轮开始判断,避免空指针异常
if(i > 0 && nums[i] == nums[i-1]) continue;
left = i + 1;
right = nums.length - 1;
sum = -nums[i];
while(left < right){
if(nums[left] + nums[right] == sum ){
ans.add(Arrays.asList(nums[i],nums[left],nums[right]));
while (left < right && nums[left] == nums[left+1]) left++;
while (left < right && nums[right] == nums[right-1]) right--;
left++;
right--;
}else if(nums[left] + nums[right] < sum)
left++;
else
right--;
}
}
return ans;
}
}