Code Ganker: Two Sum -- LeetCode

2014年2月6日星期四

Two Sum -- LeetCode

原题链接: http://oj.leetcode.com/problems/two-sum/
这是一道非常经典的题目,brute force时间复杂度为O(n^2), 对每一对pair两两比较。 优化的方法一般有两种,第一种是用哈希表,时间复杂度为O(n),同时空间复杂度也是O(n),代码如下:
public int[] twoSum(int[] numbers, int target) {
    int[] res = new int[2];
    if(numbers==null || numbers.length<2)
        return null;
    HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
    for(int i=0;i<numbers.length;i++)
    {
        if(map.containsKey(target-numbers[i]))
        {
            res[0]=map.get(target-numbers[i])+1;
            res[1]=i+1;
            return res;
        }
        map.put(numbers[i],i);
    }
    return null;
}
第二种解法是先对数组进行排序,然后使用夹逼的方法找出满足条件的pair,原理是因为数组是有序的,那么假设当前结果比target大,那么左端序号右移只会使两个数的和更大,反之亦然。所以每次只会有一个选择,从而实现线性就可以求出结果。该算法的时间复杂度是O(nlogn+n)=O(nlogn),空间复杂度取决于排序算法。代码如下:
public int[] twoSum(int[] numbers, int target) {
    int[] res = new int[2];
    if(numbers==null || numbers.length<2)
        return null;
    Arrays.sort(numbers);
    int l = 0;
    int r = numbers.length-1;
    while(l<r)
    {
        if(numbers[l]+numbers[r]==target)
        {
            res[0] = number[l];
            res[1] = number[r];
            return res;
        }
        else if(numbers[l]+numbers[r]>target)
        {
            r--;
        }
        else
        {
            l++;
        }
    }
    return null;
}
注意,在这里,输出结果改成了满足相加等于target的两个数,而不是他们的index。因为要排序,如果要输出index,需要对原来的数的index进行记录,方法是构造一个数据结构,包含数字的值和index,然后排序。所以从这个角度来看,这道题第二种解法并没有第一种解法好,空间也是O(n). 在LeetCode原题中是假设结果有且仅有一个的,一般来说面试时会要求出所有的结果,这个时候会涉及到重复pair的处理,相关的内容会在3Sum那道题目中涉及到,请参见3Sum -- LeetCode.

9 条评论:

  1. 建议博主把原题贴出来,或者给个链接,这样方便看啦。我先贴下这个:

    Given an array of integers, find two numbers such that they add up to a specific target number.

    The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

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

    Input: numbers={2, 7, 11, 15}, target=9
    Output: index1=1, index2=2

    回复删除
  2. 要求是index1<index2,没想通为什么map.get(target-numbers[i]) 一定比 i 小。

    回复删除
    回复
    1. index1<index2是因为后来进来的index比较小,target-numbers[i]是前面加的,index肯定比i小。

      删除
  3. numbers=null 和 numbers.length=0 有什么区别么?如果numbers=null是说占用地址没有用?

    回复删除
    回复
    1. numbers == null 意思是numbers是一个空指针,地址是null,numbers.length==0是说number是一个数组,长度是0,是有分配一个地址的。

      删除
  4. while(ltarget)??? 还是while(lnumbers[l]+numbers[r] != target)?

    回复删除
    回复
    1. 应该是while(l<r),网页对于字符解析出错了,现在改好了。

      删除
  5. 这道题的变种问题好多啊。。。博主分析的太好了!

    回复删除
    回复
    1. 是的哈~ 面试中经常考查更多的是对变体的应变能力,因为常见的解法估计大家准备过都会了~ 有问题可以多交流哈~

      删除