题目:力扣https://leetcode-cn.com/problems/3sum/
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<List<Integer>>();
for(int i=0;i<nums.length;i++){
if(nums[i] > 0) return ans;
if(i > 0 && nums[i] == nums[i-1]) continue;
int left = i+1;
int right = nums.length-1;
while(left<right){
if(nums[i]+nums[left]+nums[right]==0){
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[left]);
list.add(nums[right]);
ans.add(list);
while(left<right && nums[left+1]==nums[left]) left++;
while(left<right && nums[right-1]==nums[right]) right--;
left++;
right--;
}else if(nums[i]+nums[left]+nums[right]>0){
right--;
}else{
left++;
}
}
}
return ans;
}
}
思路:这题一直超时,很久都AC不了,很难受。这里大概思路是,想给传入的数组先排序,然后枚举第一个数,再利用双指针的算法找是否存在三数之和为0的元素,若有则通过add()的方法添加进list中。双指针的位置范围再枚举元素与最后一个元素之间,这样既可以避免了重复解,又节省了运行时间。遍历枚举完成后,返回ans即可。
1.准备阶段。给传入数组排序,然后声明一个二维的lis类对象ans。
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<List<Integer>>();
2.枚举第一个数。
for(int i=0;i<nums.length;i++){
//......
}
3.避免枚举重复的元素导致重复解。设置左指针与右指针的位置。
if(i > 0 && nums[i] == nums[i-1]) continue;
int left = i+1;
int right = nums.length-1;
4.双指针循环查找符合三数之和为0的元素。若找到,则通过add()的方法添加到list中,然后左右指针继续靠近,继续查找解。其中两个while语句是为了保证左右指针不会找到与之前重复的元素,从而导致重复解。如果没有匹配成功,则根据三数之和的大小判断是移动左指针还是移动右指针。若三数之和大于0,则将右指针向左移;若三数之和小于0,则将左指针向右移。
while(left<right){
if(nums[i]+nums[left]+nums[right]==0){
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[left]);
list.add(nums[right]);
ans.add(list);
while(left<right && nums[left+1]==nums[left]) left++;
while(left<right && nums[right-1]==nums[right]) right--;
left++;
right--;
}else if(nums[i]+nums[left]+nums[right]>0){
right--;
}else{
left++;
}
}
5.完成上述循环,返回ans即可。
return ans;