题目地址:https://leetcode.com/problems/3sum/
题目:
给定n个整数的数组nums,nums中是否有元素a,b,c,a + b + c = 0? 找到数组中所有唯一的三元组,它们的总和为0。
注意:
解决方案集不得包含重复的三元组。
例:
给定数组nums = [-1,0,1,2,-1,-4],
解决方案集是:
[
[-1,0,1],
[-1,-1,2]
]。
才接触的该题库题目,不是很熟悉, 我首先自己想了想,最笨的办法就是遍历所有的数字三遍,找到满足条件的首先对数组排序(时间复杂度为). 显然不是最优的结果,而且与推荐的答案有区别. 我知道了要首先进行排序. 再进行遍历. 最后就出现了需要注意的上面的问题: 解决方案集中出现了包含重复的三元组。
public List<List<Integer>> threeSum(int[] nums) {
int n = nums.length;
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i <n ; i++) {
while (i > 0 && nums[i] == nums[i-1]){
i = i+1;
}
for (int j = i+1; j < n; j++) {
while (nums[j] == nums[j-1]){
j = j+1;
}
for (int k = j+1; k < n; k++) {
while (nums[k] == nums[k-1]){
k = k+1;
}
if (nums[i] + nums[j] + nums[k] == 0){
List<Integer> yigejie = new ArrayList<>();
yigejie.add(nums[i]);
yigejie.add(nums[j]);
yigejie.add(nums[k]);
result.add(yigejie);
}
}
}
}
return result;
}
思前想后还是不得要领. 我就看了一下讨论区. 果然有高手.
public static List<List<Integer>> threeSum(int[] num) {
Arrays.sort(num); //排序
List<List<Integer>> res = new LinkedList<>();
for (int i = 0; i < num.length-2; i++) { //一个循环复杂度为n
if (i == 0 || (i > 0 && num[i] != num[i-1])) { //对数组第一个元素进行去重
int lo = i+1, hi = num.length-1, sum = 0 - num[i];//将第一个元素设为目标值
while (lo < hi) {//使用while只需遍历一遍
if (num[lo] + num[hi] == sum) {
res.add(Arrays.asList(num[i], num[lo], num[hi]));
while (lo < hi && num[lo] == num[lo+1]) lo++;//对第二元素去重
while (lo < hi && num[hi] == num[hi-1]) hi--;//对第三个元素去重
lo++; hi--;
} else if (num[lo] + num[hi] < sum) lo++;//总和小于目标值,增加第二个元素的下标
else hi--;//总和大于目标值,减小第三个元素的下标
}
}
}
return res;
}
其复杂度为. 对数组进行了两次遍历就得到了结果. https://leetcode.com/problems/3sum/discuss/7380/Concise-O(N2)-Java-solution