一、题目
- 15. 三数之和 - 力扣(LeetCode)
给你一个整数数组
nums
,判断是否存在三元组[nums[i], nums[j], nums[k]]
满足i != j
、i != k
且j != k
,同时还满足nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为
0
且不重复的三元组。注意:答案中不可以包含重复的三元组。
二、思路
- 看似要用三循环,但肯定行不通,那就用指针替代循环,维护三个指针,采用“定一动二”的思想,固定其中一个指针,剩下的部分就是常规的双指针了;
- 这道题还要注意防止内存不足,因为排序后可能会出现大量重复数据,一定要注意去重;
三、解法
解法一
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ret = new ArrayList<>();
int len = nums.length;
// 数组长度小于 3 必定无解
if (len < 3) {
return ret;
}
// 排序才能用双指针
Arrays.sort(nums);
// 外层主要定于“定一”
for (int i = 0; i < len - 2; i++) {
// 数组已排序,若当前数已大于 0
// 则当前数与双指针所指的两个同样大于 0 的数相加必定不为 0
if (nums[i] > 0) {
break;
}
// 去重 [0,0,0,1,1,2] 比较完 index=0 就没必要再比较 index=1
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
// 经典双指针应用
int left = i + 1;
int right = len - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum == 0) {
// 去重 [-2,-1,0,1,1,2] left=1 right=4
// 此时 [-1,0,1] 满足题意,但是要去重 right=3
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
ret.add(Arrays.asList(nums[i], nums[left++], nums[right--]));
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return ret;
}
}