LCR 007. 三数之和
解题思路
- 定义:定义一个名为Solution的类,并且在这个类中维护一个成员变量res,用于存储所有满足条件的三元组。
- 主方法:threeSum方法是解决问题的入口点。它调用threeSumTarget方法来计算所有和为0的三元组。
- 转化为两数之和:threeSumTarget方法首先对输入数组nums进行排序,然后遍历每个元素nums[i],并把问题转化为找出数组中的两个数,使得两数之和为target - nums[i]。这是因为我们希望nums[i] + nums[j] + nums[k] == target,即如果确定了nums[i],我们只需要在剩下的数组中找到两个数之和为target - nums[i]。
- 寻找两数之和:使用twoSumTarget方法来找出所有和为特定target值的元素对。因为数组已经排序,所以可以用双指针技术,一个从剩余数组的起始位置开始,一个从数组结束的位置开始遍历。
- 去重:在threeSumTarget和twoSumTarget方法中,该代码使用while循环来跳过重复的元素,以避免在结果集res中出现重复的三元组。
收集结果:每当在twoSumTarget找到符合条件的元组时,就会创建一个新的数组a,将成对的元素(也就是找到的两个数)添加到a中,然后将nums[i](当前遍历的元素)添加到a,最后将完整的三元组添加到结果列表res中。
返回结果:最后返回填充好的结果列表res,它包含了所有不重复的符合条件(三个数之和等于目标值target)的三元组
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> threeSum(int[] nums) {
return threeSumTarget(nums,0);
}
List<List<Integer>> threeSumTarget(int[] nums,int target){
Arrays.sort(nums);
for(int i = 0; i < nums.length; i++){
List<List<Integer>> temp = twoSumTarget(nums,i + 1,target - nums[i]);
for(List<Integer> t:temp){
t.add(nums[i]);
res.add(t);
}
while(i < nums.length - 1 && nums[i] == nums[i + 1]){
i++;
}
}
return res;
}
List<List<Integer>> twoSumTarget(int[] nums,int start,int target){
List<List<Integer>> res = new ArrayList<>();
int left = start;
int right = nums.length - 1;
while(left < right){
int sum = nums[left] + nums[right];
int l = nums[left];
int r = nums[right];
if(sum == target){
List<Integer> a = new ArrayList<>();
a.add(nums[left]);
a.add(nums[right]);
res.add(a);
while(left < right && nums[left] == l){
left++;
}
while(left < right && nums[right] == r){
right--;
}
}else if(sum < target){
while(left < right && nums[left] == l){
left++;
}
}else if(sum > target){
while(left < right && nums[right] == r){
right--;
}
}
}
return res;
}
}