仅供个人学习使用
题目描述:
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为 0
且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
题目解析:
本题的重点是去重。
我们先排序,然后固定一个元素nums[i],采用双指针。具体思路如下:
首先对数组进行排序,这样相同的数字会挨在一起,方便后续处理。逐个检查数组中的每个数字。对于每个数字,使用两个指针l和r(一个在当前数字之后,一个在数组末尾)来寻找另外两个数字,使得这三个数字的和为0。如果当前数字与前一个数字相同,跳过以避免找到相同的三元组
双指针移动:在 while
循环中,我们根据 sum
(即 nums[l] + nums[r]
)与 target
的比较结果来移动指针 l
和 r
:
- 如果
sum
等于target
,说明我们找到了一个三元组,将其添加到结果列表中。 - 如果
sum
小于target
,说明我们需要一个更大的和,因此将l
向右移动,以增加nums[l]
的值。 - 如果
sum
大于target
,说明我们需要一个更小的和,因此将r
向左移动,以减少nums[r]
的值。
找到一组解后,跳过所有重复的数字,以避免找到重复的三元组。
实现代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//排序
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList<>();
for(int i = 0; i < nums.length;i++){
//跳过重复元素
if(i>0 && nums[i] == nums[i - 1]) continue;
//双指针
int l = i + 1,r = nums.length - 1;
int target = -nums[i];
while(l < r){
int sum = nums[l] + nums[r];
if(sum == target){
res.add(Arrays.asList(nums[i], nums[l], nums[r]));
l++;
r--;
//跳过重复元素
while(l < r && nums[l] == nums[l - 1]) l++;
while(l < r && nums[r] == nums[r + 1]) r--;
}else if(sum < target){
l++;
}else r--;
}
}
return res;
}
}
标签:15,target,nums,int,三数,sum,三元组,LeetCode,数字
From: https://blog.csdn.net/m0_62909831/article/details/144129296