[leetcode-15]3Sum(java)

问题描述:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:
Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4},

A solution set is:
(-1, 0, 1)
(-1, -1, 2)

分析:这道题想到了是先排序,然后再用两个指针,left 和right,分别从两端趋近。然后当z=-(Vleft+Vright),然后在中间搜索z(二分法)。然后用递归的方法,但是却超时了。看了网友的介绍。感觉网友的方法确实很好。
其思想如下:这里有三个变量,因此,向着O(n2)的方向努力。先对数组排序,当数从前向后移动时,固定住一个数,然后再选两个数:left = i+1;right = nums.length-1;然后二者向中间逼近。当Vl+Vr+p>0时,left++l若小于0,right–。当然为0时,添加到list中。

同样,去重也是一个比较讨厌的问题,一个很好的trick是:当num[i]==num[i-1]时,此时固定的数是一样的。那么此时,搜索到的list的集合一定是num[i-1](当p为num[i-1])的子集。所以过滤。
当一个三元组找到之后(num[i],nums[j],num[k])找到时,因为此时为有序排序。所以若num[j+1]==num[j],过滤。当num[k-1]==num[k]时,过滤。此时,再没有重复的可能。

代码如下:380ms

public class Solution {
      public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new LinkedList<List<Integer>>();
        Arrays.sort(nums);//排序
        int i;
        int p;
        int left,right;
        int tmp;
        List<Integer> list;

        for(i = 0;i<nums.length;i++){
            p = nums[i];
            if(i-1>=0&&p==nums[i-1])
                continue;
            left = i+1;
            right = nums.length-1;
            while(left<right){
                tmp = nums[left]+nums[right]+p;
                if(tmp==0){
                    list = new LinkedList<Integer>();
                    list.add(p);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    res.add(list);
                    while(left+1<nums.length&&nums[left]==nums[left+1])
                        left++;
                    while (right-1>=0&&nums[right-1]==nums[right])
                        right--;
                    left++;right--;
                }else if(tmp<0)
                    left++;
                else
                    right--;
            }
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值