1. 程式人生 > >leetcode題解-15. 3Sum && 16. 3Sum Closest

leetcode題解-15. 3Sum && 16. 3Sum Closest

15,題目:

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: 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] ]

本題和TwoSum、FourSUM都是一個系列的。目的是尋找三個數和為0的子集。一種最直接的思路就是使用兩個迴圈,外迴圈遍歷整個陣列,固定第一個元素,內迴圈進行TwoSum操作,找到和為0的組合即可。程式碼入下:

    public List<List<Integer>> threeSum(int[] num) {
        Arrays.sort(num);
        List<List<Integer>> res = new ArrayList<>();
        for
(int i = 0; i < num.length-2; i++) { if (i == 0 || (i > 0 && num[i] != num[i-1])) { int lo = i+1, hi = num.length-1, sum = 0 - num[i]; while (lo < hi) { if (num[lo] + num[hi] == sum) { res.add(Arrays.asList(num[i], num[lo], num[hi])); //跳過相等的元素
while (lo < hi && num[lo] == num[lo+1]) lo++; while (lo < hi && num[hi] == num[hi-1]) hi--; lo++; hi--; } else if (num[lo] + num[hi] < sum) lo++; else hi--; } } } return res; }

另外一種思路是使用hashset來儲存遍歷過的組合,這種方法因為使用了比較複雜的資料結構,所以比較耗時,程式碼入下:

    public List<List<Integer>> threeSum1(int[] num) {
        Arrays.sort(num);
        List<List<Integer>> list = new ArrayList<>();
        HashSet<List<Integer>> set = new HashSet<>();
        for(int i=0;i<num.length;i++)
        {
            for(int j=i+1,k=num.length-1;j<k;)
            {
                if(num[i]+num[j]+num[k]==0)
                {
                    List<Integer> l= new ArrayList<Integer>();
                    l.add(num[i]);
                    l.add(num[j]);
                    l.add(num[k]);
                    if(set.add(l))
                        list.add(l);
                    j++;
                    k--;
                }
                else if(num[i]+num[j]+num[k]<0)
                    j++;
                else
                    k--;
            }
        }
        return list;
    }

16, 題目:

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

    For example, given array S = {-1 2 1 -4}, and target = 1.

    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

本題是上面題目的變種,目的是尋找和最接近target的三個數。我們直接可以使用上面的思路,不過定義一個變數來儲存結果和最小的差。程式碼如下:

    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int diff = Integer.MAX_VALUE, closest = 0;
        for (int k=0; k<nums.length-2; ++k) {
            for (int i=k+1, j=nums.length-1; i<j; ) {
                int sum = nums[k] + nums[i] + nums[j];
                if (sum == target) { return target; }
                else if (sum > target) {
                    if (sum-target < diff) {
                        diff = sum-target;
                        closest = sum;
                    }
                    --j;
                } else {
                    if (target-sum < diff) {
                        diff = target-sum;
                        closest = sum;
                    }
                    ++i;
                }
            }
        }
        return closest;
    }