// 首先我们遍历数组找到数组的最大值和最小值以及 0 的个数。 如果0的个数大于或等于3,那么 三个 0 是其中的一个答案。 三个数的和为0,除了三个数都为0的答案之外,在其它答案的三个数中,至少都要有一个正数和一个负数。如果数组没有负数或正数, 那就没有其它答案了,可以直接返回。
// 根据数据的大小范围,我们可以用计数排序对整个数组进行计数,然后把负数从大到小放到数组negNums和把正数从小到大放到数组posNums中。从大到小遍历负数数组得到一个负数negNum,和从小到大遍历正数数组的到一个正数posNum,那么第三个数x的值为- negNum - posNum。当x在数组中存在(x和negNum或posNum相等的时候,在数组中至少有两个数值为x的数),那么negNum,posNum 和 x 则为其中的一个答案。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ret = new ArrayList<>();
Arrays.sort(nums); //数组排序
int n = nums.length;
for (int i = 0; i < n; i++) {
//不存在负数结束
if (nums[i] > 0) {
break;
}
//重复跳过
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int l = i + 1, r = n - 1;
while (l < r) {
int sum = nums[l] + nums[r] + nums[i];
if (sum == 0) {
ret.add(Arrays.asList(nums[i], nums[l], nums[r]));
while (r > 0 && nums[r] == nums[r - 1]) {
r--;
}
while (l < n - 1 && nums[l] == nums[l + 1]) {
l++;
}
}
//总数大于0,最大值向里面减小,反之则最小值后挪增大
if (sum > 0) {
r--;
} else {
l++;
}
}
}
return ret;
}
}