Leetcode 15 3Sum

来源:互联网 发布:淘宝每日精选怎么加入 编辑:程序博客网 时间:2024/06/05 18:08

3Sum

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) 

Solution1

  • 类似于这种K Sum的问题,基本都是固定第一个数,然后再将问题转化为(K-1) Sum的子问题,最终通过层层嵌套的for循环将问题转化为2 Sum问题。时间复杂度为
    Math.max(O(NlogN),O(NK1))

    前者为当K=2时取排序的时间复杂度。代码如下:
import java.util.Arrays;import java.util.ArrayList;import java.util.List;public class Solution {    public List<List<Integer>> threeSum(int[] nums) {        ArrayList<List<Integer>> result = new ArrayList<List<Integer>>();        Arrays.sort(nums);        for(int i=0;i<nums.length;i++){            if(i<nums.length&&i>0&&nums[i-1]==nums[i]) continue;//如果之前已访问过相同的则跳过            int target = -1*nums[i];            for(int k=i+1,j=nums.length-1;k<j;){                if(nums[k]+nums[j]<target) k++;                else if(nums[k]+nums[j]>target) j--;                else{                    ArrayList<Integer> temp = new ArrayList<Integer>();                    temp.add(nums[i]);                    temp.add(nums[k++]);                    temp.add(nums[j--]);                    result.add(temp);                    while(k<j&&k>0&&nums[k-1]==nums[k]) k++;//如果之前已访问过相同的则跳过                    //while(k<j&&j<nums.length-1&&nums[j+1]==nums[j]) j--;//对于j来说,不需要判断是否重复,因为只要前面两个数不重复,j不可能重复了                }            }        }        return result;            }}

Solution2

  • 解法1是利用判断和之前的数是否相同来去重复的,当然也可以用两个两边记录前一次已访问过的数,代码如下:
import java.util.Arrays;import java.util.ArrayList;import java.util.List;public class Solution {    public List<List<Integer>> threeSum(int[] nums) {        ArrayList<List<Integer>> result = new ArrayList<List<Integer>>();        Arrays.sort(nums);        for(int i=0,prev1=Integer.MIN_VALUE;i<nums.length;prev1=nums[i++]){//prev1记录第一个数            if(nums[i]==prev1) continue;//如果之前已访问过相同的则跳过            int target = -1*nums[i];            for(int k=i+1,j=nums.length-1,prev2=Integer.MIN_VALUE;k<j;){//prev2来记录第二个数                if(nums[k]==prev2||nums[k]+nums[j]<target) k++;                else if(nums[k]+nums[j]>target) j--;                else{                    prev2 = nums[k];                    ArrayList<Integer> temp = new ArrayList<Integer>();                    temp.add(nums[i]);                    temp.add(nums[k++]);                    temp.add(nums[j--]);                    result.add(temp);                }            }        }        return result;        }}
  • 这种题思路非常清晰,但是对于去重,一定要小心。最简便的方法还是利用解法二中的分别用一个变量去保存之前的那个数,如果和之前的那个数相同则往后继续遍历。
0 0