题目:
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意 答案中不可以包含重复的三元组。
示例
输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
题目要求我们找到数组nums中所有不重复的三元组[nums[i], nums[j], nums[k]],使得i != j、i != k且j != k,同时满足nums[i] + nums[j] + nums[k] == 0。
解题思路:
-
排序数组:首先对输入的数组
nums进行排序。排序后的数组有助于后续处理,特别是跳过重复元素和使用双指针策略。 -
外层循环:遍历排序后的数组,使用变量
i作为第一个元素的索引。在每次迭代开始时,检查i是否大于0且当前元素nums[i]是否与前一个元素相同。如果是,则跳过当前迭代,以避免重复的三元组。 -
双指针策略:
- 初始化两个指针
left和right,分别指向i的下一个位置和数组的最后一个元素。 - 计算当前三元组的和
sum = nums[i] + nums[left] + nums[right]。 - 如果
sum小于0,说明需要更大的值来达到和为0,因此移动left指针向右。 - 如果
sum大于0,说明需要更小的值,因此移动right指针向左。 - 如果
sum等于0,说明找到了一个有效的三元组,将其添加到结果列表result中。
- 初始化两个指针
-
跳过重复元素:
- 在找到一个有效的三元组后,需要确保
left和right指针不会指向之前已经考虑过的元素,以避免重复的三元组。 - 通过检查
left和right指针的下一个和前一个元素是否与当前元素相同,来跳过重复的元素。如果相同,则移动指针直到遇到不同的元素。
- 在找到一个有效的三元组后,需要确保
-
返回结果:当外层循环结束时,返回包含所有有效三元组的结果列表
result。
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1, right = nums.length - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum < 0) {
left++;
} else if (sum > 0) {
right--;
} else {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
left++;
right--;
}
}
return result;
之前用了俩循环 没想到超时了o(╥﹏╥)o