LeetCode:三数之和【15】
题目描述
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
题目分析
我试了很多方法尝试去解决这个问题,但是都无果。后来在一次算法课上讲到了这个问题,3Sum问题,当时讨论出的解决方法如下:
List<List<Integer>> mylist = new ArrayList<>();
Arrays.sort(nums);
for(int i=0;i<nums.length;i++) {
for (int j = i+1;j<nums.length;j++) {
int k=Arrays.binarySearch(nums,-(nums[i]+nums[j]));
if(k>j)
{
ArrayList<Integer> al = new ArrayList<>();
al.add(nums[i]);al.add(nums[j]);al.add(nums[k]);
if(!mylist.contains(al))
mylist.add(al);
}
}
}
return mylist;
}
当时我对这个结局方案非常满意,可是现在不这么认为了。如果给出的数组是[0,0,0,0],那么就无法解决。
因为第三个值为0,无论如何到找到的都是中间那个,K不可能大于J。何况J还在自增。但是无论如何这是我们思考后的东西,都是有价值的。
Java题解
public List<List<Integer>> threeSum(int[] nums) {
/*
思路:从数组序列0开始依次取数作为第一个数字,剩下的两个数字指针从 数组的序列两端开始 相向取数字
并且每次都计算3个数的和,如为0则添加到列表,不为0,则根据和的大小,分别移动左右指针。 */
List<List<Integer>> result = new ArrayList<>();
if(nums.length < 3) return result;
Arrays.sort(nums);
int i = 0;
while(i < nums.length - 2) {
if(nums[i] > 0) break; int j = i + 1; //左指针
int k = nums.length - 1; //右指针 while(j < k) {
int sum = nums[i] + nums[j] + nums[k];
if(sum == 0) result.add(Arrays.asList(nums[i], nums[j], nums[k]));
if(sum <= 0) while(nums[j] == nums[++j] && j < k); //实现越过重复数字的功能
if(sum >= 0) while(nums[k--] == nums[k] && j < k); //同样实现越过重复数字的功能
} while(nums[i] == nums[++i] && i < nums.length - 2);//同上
}
return result;
}
反思
1.对 while循环的进一步理解:
while(nums[i]=nums[++j]&&j<k)
根据这条命令即可实现越过重复数字的功能.
2.双指针技术的应用。