LeetCode Top 100 Liked Questions 15.3Sum (Java版; Medium)

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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值