15. 三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
class Solution {
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> rst = new ArrayList<>();
List<Integer> list = new ArrayList<>();
// 排序,找到第一个非负数
Arrays.sort(nums);
int mid = 0;
// 如果最大的数和最小的数同号,那么没有答案直接返回空
if (nums[nums.length - 1] * nums[0] > 0) {
return rst;
}
for (int num : nums) {
if (num >= 0) {
break;
}
mid++;
}
int i = 0, j = nums.length - 1;
int t = 0;
// 如果最大的两个数加最小的负数都小于零,说明最小的负数太小了,右移左边指针
// 如果最小的两个数加最大的正数都大于零,说明最大的正数太大了,左移右边指针
while (true) {
if (i + 1 < j && nums[i] + nums[i + 1] + nums[j] > 0) {
j--;
} else if (j - 1 > i && nums[j] + nums[j - 1] + nums[i] < 0) {
i++;
} else {
break;
}
}
t = i;
// 定住右边指针,右移左边指针到第一个非负数为止,然后重置左边指针的同时左移右边指针
while (i < j) {
if (nums[i] + nums[j] <= 0) {
for (int k = mid; k < j; k++) {
if (nums[i] + nums[j] + nums[k] == 0 && k != i) {
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
break;
}
}
} else {
for (int k = i + 1; k < mid; k++) {
if (nums[i] + nums[j] + nums[k] == 0 && k != j) {
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
break;
}
}
}
i++;
if (i == mid) {
if (mid + 1 < j && nums[i] + nums[mid + 1] + nums[j] == 0) {
list.add(nums[i]);
list.add(nums[mid + 1]);
list.add(nums[j]);
}
j--;
i = t;
}
if (list.size() != 0) {
rst.add(list);
}
list = new ArrayList<>();
}
// 轮子去重
Set<List<Integer>> set = new LinkedHashSet<>(rst);
rst.clear();
rst.addAll(set);
return rst;
}
}
总结
执行时间达到了逆天的1900ms+,但是好歹写出来了,花的时间也不太长。