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
Naive方法:Time Limit Exceeded, 算法复杂度到了O(N^2),自然就TLE了
而且有一些小语法错误需要注意:for(runner=current+1;;)不能用>;一定所有的case都有return情况,我如果把return写在if语句里,一定要确定不进if语句也要有相应的return情况。
1 public class Solution { 2 public int[] twoSum(int[] numbers, int target) { 3 int[] results=new int[2]; 4 if(numbers==null) return null; 5 for(int current=0; current<numbers.length; current++){ 6 for(int runner=current+1; runner<numbers.length; runner++){ 7 if((numbers[current]+numbers[runner])==target){ 8 results[0]=current+1; 9 results[1]=runner+1; 10 return results; 11 } 12 } 13 } 14 return null; 15 } 16 }
第二遍做法,用Hashtable, 把时间复杂度降低到了O(N),并且11行还检查不是自己跟自己,话说这道题其实不用做这个检查,因为题目ganrantee一定有一组解,而且这组解是两个不同的数字,所以不存在自己加自己等于target的情况。其实这道题暗示所有数是unique的,这样才能用HashMap。不是Unique的情况,要复杂很多
1 public class Solution { 2 public int[] twoSum(int[] numbers, int target) { 3 int[] res = new int[2]; 4 HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); 5 for (int i=0; i<numbers.length; i++) { 6 map.put(numbers[i], i); 7 } 8 for (int i=0; i<numbers.length; i++) { 9 if (map.containsKey(target-numbers[i])) { 10 int index = map.get(target-numbers[i]); 11 if (i == index) continue; 12 res[0] = Math.min(i, index)+1; 13 res[1] = Math.max(i, index)+1; 14 } 15 } 16 return res; 17 } 18 }
贴个别人(Code Ganker)的solution, 也是用hashmap,这个方法要比我上面快一点,因为它一边插一边找
1 public int[] twoSum(int[] numbers, int target) { 2 int[] res = new int[2]; 3 if(numbers==null || numbers.length<2) 4 return null; 5 HashMap<Integer,Integer> map = new HashMap<Integer,Integer>(); 6 for(int i=0;i<numbers.length;i++) 7 { 8 if(map.containsKey(target-numbers[i])) 9 { 10 res[0]=map.get(target-numbers[i])+1; 11 res[1]=i+1; 12 return res; 13 } 14 map.put(numbers[i],i); 15 } 16 return null; 17 }
他还有第二种方法,先对数组进行排序,然后使用夹逼的方法找出满足条件的pair,原理是因为数组是有序的,那么假设当前结果比target大,那么左端序号右移只会使两个数的和更大,反之亦然。所以每次只会有一个选择,从而实现线性就可以求出结果。该算法的时间复杂度是O(nlogn+n)=O(nlogn),空间复杂度取决于排序算法。代码如下:注意,在这里,输出结果改成了满足相加等于target的两个数,而不是他们的index。因为要排序,如果要输出index,需要对原来的数的index进行记录,方法是构造一个数据结构,包含数字的值和index,然后排序。所以从这个角度来看,这道题第二种解法并没有第一种解法好,空间也是O(n)
1 public int[] twoSum(int[] numbers, int target) { 2 int[] res = new int[2]; 3 if(numbers==null || numbers.length<2) 4 return null; 5 Arrays.sort(numbers); 6 int l = 0; 7 int r = numbers.length-1; 8 while(l<r) 9 { 10 if(numbers[l]+numbers[r]==target) 11 { 12 res[0] = number[l]; 13 res[1] = number[r]; 14 return res; 15 } 16 else if(numbers[l]+numbers[r]>target) 17 { 18 r--; 19 } 20 else 21 { 22 l++; 23 } 24 } 25 return null; 26 }