welcome to my blog
LeetCode Top 100 Liked Questions 15.3Sum (Java版; Medium)
题目描述
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0?
Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
绊脚案例
加入了重复组合
输入:
[-2,0,0,2,2]
输出
[[-2,0,2],[-2,0,2]]
预期结果
[[-2,0,2]]
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int n = nums.length;
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
int cur,L,R;
for(int i=0; i<n; i++){
if(i-1>=0 && nums[i]==nums[i-1]){
continue;
}
cur = nums[i];
L = i+1;
R = n-1;
int target = -cur;
while(L<R){
int sum = nums[L] + nums[R];
if(sum == target){
List<Integer> al = new ArrayList<>();
al.add(cur);
al.add(nums[L]);
al.add(nums[R]);
list.add(al);
L++;
R--;
while(L<R && nums[L]==nums[L-1]){
L++;
}
while(R>L && nums[R]==nums[R+1]){
R--;
}
}else if(sum > target){
R--;
}else{
L++;
}
}
}
return list;
}
}
第一次做; 先对数组排序; 每次选定一个值, 再用双指针选取另外两个值; 双指针在有序数组中往往比较容易确定移动方向; 本题中有两个地方需要跳过处理过的元素:参照值处理过 或者 另外两个值出现过,见绊脚案例; 注意检查数组索引是否越界
- 双指针与有序数组
- 参照值大于0的话就break, 因为参照值是最小的, 不可能再有三个数相加和为0的情况了
- 出现过
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
if(nums==null || nums.length<3)
return res;
Arrays.sort(nums);
int left, right, curr;
for(int i=0; i<nums.length-2; i++){
//initialize; update
left = i+1;
right = nums.length - 1;
//小优化, 最小值大于0的话, 三个数相加一定大于0, 跳出循环
if(nums[i]>0)
break;
//出现过的元素不再进行处理, 之前已经处理过了
if(i>0 && nums[i]==nums[i-1])
continue;
//execute
while(left<right){
curr = nums[i] + nums[left] + nums[right];
if(curr>0)
right--;
else if(curr<0)
left++;
//相同的组合不再加入
else if(left >= i+2 && nums[left]==nums[left-1] && nums[right]==nums[right+1]){
left++;
right--;
continue;
}
else
{
res.add(new ArrayList<Integer>());
res.get(res.size()-1).add(nums[i]);
res.get(res.size()-1).add(nums[left]);
res.get(res.size()-1).add(nums[right]);
//update
left++;
right--;
}
}
}
return res;
}
}
优秀答案; res添加元素时使用了Arrays.asList(); 重复元素的处理都用的while
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList<>();
for(int k = 0; k < nums.length - 2; k++){
if(nums[k] > 0) break;
if(k > 0 && nums[k] == nums[k - 1]) continue;
int i = k + 1, j = nums.length - 1;
while(i < j){
int sum = nums[k] + nums[i] + nums[j];
if(sum < 0){
while(i < j && nums[i] == nums[++i]);
} else if (sum > 0) {
while(i < j && nums[j] == nums[--j]);
} else {
res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));
while(i < j && nums[i] == nums[++i]);
while(i < j && nums[j] == nums[--j]);
}
}
}
return res;
}
}