Leetcode 1. Two Sum & 15. 3Sum & 16. 3Sum Closest & 18. 4Sum

来源:互联网 发布:乐高ev3编程软件简介 编辑:程序博客网 时间:2024/05/22 17:36

1. Two Sum

Total Accepted: 196496 Total Submissions: 907244 Difficulty: Medium

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution.

Example:

Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

UPDATE (2016/2/13):
The return format had been changed to zero-based indices.

 Please read the above updated description carefully.


Method大体思想就一个,HashMap。

版本1,自己写的,因为<key,value> key应该唯一,因此key是index,value是值。

public class Solution { // 182ms    public int[] twoSum(int[] nums, int target) {        int[] res = new int[2];        HashMap<Integer,Integer> hmap = new HashMap<Integer,Integer>();        if (nums == null || nums.length<3) return res;                for (int i = 0; i<nums.length; i++)        {            if (hmap.containsValue(target-nums[i]))            {                res[1] = i;                for (int key : hmap.keySet())                {                    if (hmap.get(key)==target-nums[i])                    {                        res[0] = key;                        return res;                    }                }            }else            {                hmap.put(i,nums[i]);            }        }        return res;    }}

必须不服,上网找来版本2:

public class Solution {    public int[] twoSum(int[] numbers, int target) {        if(numbers.length>=2)        {            HashMap<Integer,Integer> h = new HashMap<Integer,Integer>();            for(int i=0; i<numbers.length; i++){                if(!h.isEmpty() && h.containsKey(target-numbers[i]))                {                    int[] k = {h.get(target-numbers[i]),i};                    return k;                }                h.put(numbers[i],i);            }        }        int[] k = {-1,-1};        return k;    }}

运行时间是7ms。。仔细一看,我说哥们,你这代码key, value反过来了啊,这不符合map定义啊!!!后来一

看题,只有一个解,那意思是就算元素重复了也OK,只要输出一个解就行。


于是把自己之前的代码key, value交换了一下,6ms:

public class Solution {    public int[] twoSum(int[] nums, int target) {        int[] res = new int[2];        HashMap<Integer,Integer> hmap = new HashMap<Integer,Integer>();        if (nums == null || nums.length<3) return res;                for (int i = 0; i<nums.length; i++)        {            if (hmap.containsKey(target-nums[i]))            {                res[1] = i;                res[0] = hmap.get(target-nums[i]);                return res;            }else            {                hmap.put(nums[i],i);            }        }        return res;


15. 3Sum

Total Accepted: 105161 Total Submissions: 570987 Difficulty: Medium

Given an array S of n integers, are there elements abc 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)

3sum网上解法大同小异。先取一个点,然后进行2sum,因为要去重,所以移动指针的时候需要判定当前

元素和之前所指的元素是否相同,如果相同则继续移动。

三个指针就有3个地方需要判断去重。

public class Solution {  //8ms    public List<List<Integer>> threeSum(int[] nums) {          List<List<Integer>> res = new ArrayList<List<Integer>>();          int len=nums.length;          if(len<3)return res;          Arrays.sort(nums);          for(int i=0;i<len;i++){              if(nums[i]>0)break;              if(i>0 && nums[i]==nums[i-1])continue;  // 去重            int begin=i+1,end=len-1;              while(begin<end){                  int sum=nums[i]+nums[begin]+nums[end];                  if(sum==0){                      List<Integer> list = new ArrayList<Integer>();                      list.add(nums[i]);list.add(nums[begin]);list.add(nums[end]);                      res.add(list);                      begin++;end--;                      while(begin<end && nums[begin]==nums[begin-1])begin++;  <span style="font-family: Arial, Helvetica, sans-serif;">//  去重</span>                    while(begin<end && nums[end]==nums[end+1])end--;  //  去重                }else if(sum>0)end--;                  else begin++;              }          }          return res;      }  }  


16. 3Sum Closest

Total Accepted: 69789 Total Submissions: 244144 Difficulty: Medium

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).


用一个变量代表目前的最小diff,如果sum比当前diff小,则更新,否则继续循环,最后输出最小diff。

版本一,自己写的:

public class Solution { //12ms    public int threeSumClosest(int[] nums, int target) {        int diff = Integer.MAX_VALUE;        int sum, begin, end, res=-1;        Arrays.sort(nums);        for (int i=0;i<nums.length;i++)        {            begin=i+1;end=nums.length-1;            while(begin<end)            {                sum = nums[i]+ nums[begin]+nums[end];                if (sum==target) return target;                if(Math.abs(sum-target)<diff)                {                    diff=Math.abs(sum-target);                    res=sum;                }                if(sum>target) end--;                else begin++;            }        }        return res;    }}

版本二:

public class Solution {//10ms    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;    }}


18. 4Sum

Total Accepted: 65299 Total Submissions: 279841 Difficulty: Medium

Given an array S of n integers, are there elements abc, and d in S such that 

a + b + c + d = target? 

Find all unique quadruplets in the array which gives the sum of target.

Note:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
  • The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
    A solution set is:
    (-1,  0, 0, 1)
    (-2, -1, 1, 2)
    (-2,  0, 0, 2)

方法一:

延续sum系列思想,取第一个点,fix住,然后取第二个点,fix住,之后进行two pointers以前一后直到

相遇,然后移动前两个点,符合条件就输出。

去重方式同3sum。

public class Solution{ //56mspublic static List<List<Integer>> fourSum(int[] nums, int target) {    if(nums==null||nums.length==0)        return new ArrayList<List<Integer>>();    Arrays.sort(nums);    int len=nums.length;    List<List<Integer>> result=new ArrayList<List<Integer>>();    for(int i=0;i<len-3;i++){        if(i>0&&nums[i]==nums[i-1])            continue;        for(int j=i+1;j<len-2;j++){            if(j>i+1&&nums[j]==nums[j-1])                continue;            int sum=target-nums[i]-nums[j],slow=j+1,fast=len-1;            while(slow<fast){                if(nums[slow]+nums[fast]==sum){                    List<Integer> tmp=new ArrayList<Integer>();                    tmp.add(nums[i]);                    tmp.add(nums[j]);                    tmp.add(nums[slow]);                    tmp.add(nums[fast]);                    result.add(tmp);                    while(slow<fast&&nums[slow]==nums[slow+1])                        slow++;                    slow++;                    while(fast>slow&&nums[fast]==nums[fast-1])                        fast--;                    fast--;                }                else if(nums[slow]+nums[fast]>sum)                    fast--;                                 else                    slow++;                                 }        }    }    return result;    }}

方法二:可以看到方法一用了56MS,因为有很多不用判断的情况,下面这个版本很巧妙,固定了首尾

两个元素,因为这两个元素可以帮忙判断是否需要跳过当前情况。如果首元素大于target/4,则因为元

素递增,则再往后的case不需要考虑了;如果尾元素小于targer/4,则因为元素递增,则再往前

case不用考虑。

public class Solution { //11ms    public List<List<Integer>> fourSum(int[] nums, int target) {        List<List<Integer>> list = new ArrayList<List<Integer>>();        Arrays.sort(nums);        int second = 0, third = 0;        for(int i=0, L=nums.length; i<L-3; i++) {            if(nums[i]<<2 > target) return list; // return immediately            for(int j=L-1; j>i+2; j--) {                if(nums[j]<<2 < target) break; // break immediately                int rem = target-nums[i]-nums[j];                int lo = i+1, hi=j-1;                while(lo<hi) {                    int sum = nums[lo] + nums[hi];                    if(sum>rem) --hi;                    else if(sum<rem) ++lo;                    else {                        list.add(Arrays.asList(nums[i],nums[lo],nums[hi],nums[j]));                        while(++lo<=hi && nums[lo-1]==nums[lo]) continue; // avoid duplicate results                        while(--hi>=lo && nums[hi]==nums[hi+1]) continue; // avoid duplicate results                    }                }                while(j>=1 && nums[j]==nums[j-1]) --j; // skip inner loop            }            while(i<L-1 && nums[i]==nums[i+1]) ++i; // skip outer loop        }        return list;    }}

至于网上的其他解法,比如backtracking,还有Ksum的通解,博主才leetcode第一遍,时间压力很大,选择

暂时跳过。目前来说选择自己能理解的方法好些。

0 0
原创粉丝点击