中等难度的题目:三数之和。有点开始饶了😥。所有的注释都在代码里面了
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k
同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k
* 同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
* <p>
* 你返回所有和为 0 且不重复的三元组。
* <p>
* 注意:答案中不可以包含重复的三元组。
*/
public class 三数之和 {
public static void main(String[] args) {
int[] nums = {-1, 0, 1, 2, -1,-1, -4};
/**
* 解题的重点是:如何去重。不然按照简单的三重循环即可解决(就如下面所示)
*/
System.out.println(threeSum(nums));
/**
* 简单的三重循环 ;没有去重
*/
// List list = new ArrayList<>();
// List result = new ArrayList<>();
// int length = nums.length;
// for (int i = 0; i < length; i++) {
// for (int j = i + 1; j < length; j++) {
// for (int k = i + 2; k < length; k++) {
// if (nums[i] + nums[j] + nums[k] == 0) {
// list.add(nums[i]);
// list.add(nums[j]);
// list.add(nums[k]);
// result.add(list);
// }
// }
// }
// break;
// }
// System.out.println(result.stream().distinct().collect(Collectors.toList()));
}
public static List<List<Integer>> threeSum(int[] nums) {
//数组为空,或者长度小于3的直接返回空
List<List<Integer>> lists = new ArrayList<>();
if (nums == null || nums.length < 3) {
return lists;
}
//先排序,再进行处理
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) { //因为是排序的,第一个都大于0 ,那么后面的和更加大于0;所以直接返回
return lists;
}
//这里 i>0 是因为我们循环的第一个元素的下标是0
if (i > 0 && nums[i] == nums[i - 1]) { //跳过重复的元素 ,避免出现重复解
continue;
}
//每次循环是:当前下标,当前下标+1,最后的边下标
int curr = nums[i];//当前值
int l = i + 1, r = nums.length - 1; //左右指针
while (l < r) {
int tmp = curr + nums[l] + nums[r];
if (tmp == 0) { //
List<Integer> list = new ArrayList<>();
list.add(curr);
list.add(nums[l]);
list.add(nums[r]);
lists.add(list);
/**
*移动左右指针的时候,需要判断是否重复,重复就跳过即可
*/
while (l < r && nums[l + 1] == nums[l]) { //和上面一致,跳过重复的值,避免出现重复解
++l;
}
/**
* 这里只移动左指针也行,提交 leetcode 也能通过,但是击败的用户会变少。
*/
// while (l < r && nums[r - 1] == nums[r]) {
// --r;
// }
++l;
// --r;
} else if (tmp < 0) { //和小于 0 ,需要将左指针+1
++l;
} else { //和大于 0 ,需要将右指针-1
--r;
}
}
}
return lists;
}
}