LeetCode:三数之和【15】

LeetCode:三数之和【15】

题目描述

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

题目分析

我试了很多方法尝试去解决这个问题,但是都无果。后来在一次算法课上讲到了这个问题,3Sum问题,当时讨论出的解决方法如下:

List<List<Integer>> mylist = new ArrayList<>();
            Arrays.sort(nums);
            for(int i=0;i<nums.length;i++) {
                for (int j = i+1;j<nums.length;j++) {
                    int k=Arrays.binarySearch(nums,-(nums[i]+nums[j]));
                    if(k>j)
                    {
                        ArrayList<Integer> al = new ArrayList<>();
                        al.add(nums[i]);al.add(nums[j]);al.add(nums[k]);
                        if(!mylist.contains(al))
                            mylist.add(al);
                    }
                }
            }
            return mylist;
}

当时我对这个结局方案非常满意,可是现在不这么认为了。如果给出的数组是[0,0,0,0],那么就无法解决。

因为第三个值为0,无论如何到找到的都是中间那个,K不可能大于J。何况J还在自增。但是无论如何这是我们思考后的东西,都是有价值的。

Java题解

    public List<List<Integer>> threeSum(int[] nums) {
        /*
            思路:从数组序列0开始依次取数作为第一个数字,剩下的两个数字指针从 数组的序列两端开始 相向取数字
                    并且每次都计算3个数的和,如为0则添加到列表,不为0,则根据和的大小,分别移动左右指针。
        
        */
        List<List<Integer>> result = new ArrayList<>();
        if(nums.length < 3) return result;
        Arrays.sort(nums);
        int i = 0;
        while(i < nums.length - 2) { 
            if(nums[i] > 0) break;
            
            int j = i + 1; //左指针
            int k = nums.length - 1; //右指针
            
            while(j < k) {
                int sum = nums[i] + nums[j] + nums[k];
                if(sum == 0) result.add(Arrays.asList(nums[i], nums[j], nums[k]));
                if(sum <= 0) while(nums[j] == nums[++j] && j < k); //实现越过重复数字的功能
                if(sum >= 0) while(nums[k--] == nums[k] && j < k); //同样实现越过重复数字的功能
            }
            
            while(nums[i] == nums[++i] && i < nums.length - 2);//同上
        }
        return result;
    }

反思

  1.对 while循环的进一步理解:

    while(nums[i]=nums[++j]&&j<k)

     根据这条命令即可实现越过重复数字的功能.

  2.双指针技术的应用。   

 

posted @ 2016-09-27 16:30  子烁爱学习  阅读(276)  评论(0编辑  收藏  举报