新手做LeetCode(15. 3Sum)

来源:互联网 发布:javascript美元符 编辑:程序博客网 时间:2024/04/30 02:39

题目如下:

package com.hll.LeetCode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 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)

 *
 */
public class Fifteen_3Sum {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> results = new ArrayList<List<Integer>>();
        
        Arrays.sort(nums);
        if(nums == null || nums.length == 0)
        {
            return results;
        }
        
        if(nums[0] > 0 || nums[nums.length - 1] < 0)
        {
            return results;
        }
        
        for(int i = 0 ; i < nums.length - 2; i++)
        {
            //如果是第一次遇见这个数(即后一个数字如果跟前一个数字相同
            //那么就跳过这个数字)
            if(i > 0 && nums[i] == nums[i - 1])
            {
                continue;
            }
            
            int left = i + 1;
            int right = nums.length - 1;
            
            int sum = - nums[i];
            while(left < right )
            {
                if(nums[left] + nums[right] == sum)
                {
                    List<Integer> result = new ArrayList<Integer>();
                    result.add(nums[i]);
                    result.add(nums[left]);
                    result.add(nums[right]);
                    results.add(result);
                    while (left < right && nums[right] == nums[right - 1]){
                        right--;
                    }
                    right--;
                    while (left < right && nums[left] == nums[left+1]){
                        left++;
                    }
                    left++;
                    continue;
                }
                
                if(nums[left] + nums[right] < sum)
                {
                    left ++ ;
                    while(left < right && nums[left] == nums[left - 1])
                    {
                        left ++ ;
                    }
                    continue;
                }
                
                if(nums[left ]+ nums[right] > sum)
                {
                    right -- ;
                    while(left < right && nums[right] == nums[right + 1])
                    {
                        right -- ;
                    }
                    continue;
                }
            }
        }
        return results;
    }
    public static void main(String[] args) {
        int[] test = {0,0,0};
        int[] test2 = {3,-9,3,9,-6,-1,-2,8,6,-7,-14,-15,-7,5,2,-7,-4,2,-12,-7,-1,-2,1,-15,-13,-4,0,-9,-11,7,4,7,13,14,-7,-8,-1,-2,7,-10,-2,1,-10,6,-9,-1,14,2,-13,9,10,-7,-8,-4,-14,-5,-1,1,1,4,-15,13,-12,13,12,-11,12,-12,2,-3,-7,-14,13,-9,7,-11,5,-1,-2,-1,-7,-7,0,-7,-4,1,3,3,9,11,14,10,1,-13,8,-9,13,-2,-6,1,10,-5,-6,0,1,8,4,13,14,9,-2,-15,-13};
        int[] test3= {-2,-3,0,0,-2};
        int[] test4 = {-2,0,0,2,2};
        long begin = System.currentTimeMillis();
        System.out.println(new Fifteen_3Sum().threeSum(test4));
        System.out.println(System.currentTimeMillis() - begin + " ms ");
    }

}

题目要求是给输入一个整数的数组,输出包含有一个包含三个整数的list,这三个整数要求和为0。且这包含三个整数的list不能有重复

看到这个题目,不考虑时间,第一反应就是一个三重循环。提交后发现超时。于是看了下discuss里的代码。现对其中一个代码的逻辑进行整理如下(不考虑边界条件)。


1.首先是对这个数组进行排序(升序)。接着就遍历这个数组。

2.如果不是第一次遇到的整数,那么就继续遍历。

3.如果是第一次遇到的整数,那么就获取这个整数nums[i]之后的后一个整数nums[i+1],记作nums[left],获取这个数组的最后一个数,记作nums[right]。对nums[i]取反,

得sum = - nums[i].

当nums[left] < nums[right]时,就继续进行如下循环:

如果nums[left] + nums[right] == sum ,那么就将nums[i],nums[left],nums[right]加入答案中;

如果nums[left] < nums[right] 且 nums[left] + nums[right] > sum ,left ++ ;

如果nums[left] < nums[right]且 nums[left] + nums[right] < sum , right ++ ;


如果是让人来做,可能是这样的。首先仍是升序排序。接着就是这样

为了避免遗漏,我就从-31开始。然后需要找到两个和是31的数。接着从-23(nums[left])和38(nums[right])开始,他们的和是15,小于31,因此需要增大他们。于是我就

看到了-20,-20 + 38 = 18 ,小于31,还是小,继续往左,一直到-7,正好等于31.于是找到了第一组符合条件的三个数。继续,我又把-5当成nums[left],23当成nums[right],继续这个过程:-5 + 23 = 18 < 31,继续往左,一直到nums[left] = 13,这时 13 + 23 = 36,大于了31,于是我把20当成了nums[right],然后继续这个过程一直到把13当成nums[right]。这样就找到了包含-31的最后一组答案。再接着就发现nums[left]>nums[right],于是又从-23开始整个过程。




       







0 0
原创粉丝点击