【LeetCode】Two Sum

Two Sum

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

Solution:

如果只是简单的:

1 class Solution:
2     # @return a tuple, (index1, index2)
3     def twoSum(self, num, target):
4         for i in range(len(num)):
5             numJ = target-num[i]
6             if numJ in num:
7                 return (i+1, num.index(numJ)+1)
8         

肯定是会超时的。这个Python程序应该是O(n^3)的(for, 查找numJ, index(numJ)),一般的O(n^2)(用for将查找值和索引合成一个循环)也会超时。

于是很快可以想到另外一种解法:QuickSort + BinarySearch。这是一般的想法,是可以AC的(O(nlogn))。

代码如下:

 1 void sort(int a[], int b[], int l, int r)
 2 {
 3     int i, j, x, t;
 4     i = l; j = r; x = a[i + ((j - i) >> 1)];
 5     do
 6     {
 7         while (x > a[i]) i++;
 8         while (x < a[j]) j--;
 9         if (i <= j)
10         {
11             t = a[i]; a[i] = a[j]; a[j] = t;
12             t = b[i]; b[i] = b[j]; b[j] = t;
13             i++; j--;
14         }
15     } while (i <= j);
16     if (i < r) sort(a, b, i, r);
17     if (j > l) sort(a, b, l, j);
18 }
19
20 int binSearch(int a[], int e, int lo, int hi)
21 {
22     int mi;
23     while (lo < hi)
24     {
25         mi = (lo + hi) >> 1;
26         if (e < a[mi]) hi = mi;
27         else lo = mi + 1;
28     }
29     return --lo;
30 }
31
32 int *twoSum(int numbers[], int n, int target) {
33     int *index = (int *)malloc(n * sizeof(int));
34     int i, indexLook;
35     int *ans = (int *)malloc(2 * sizeof(int));
36     for (i = 0; i<n; i++) index[i] = i;
37     sort(numbers, index, 0, n-1);
38     for (i = 0; i<n; i++)
39     {
40         indexLook = binSearch(numbers, target - numbers[i], 0, n);
41         if (numbers[indexLook] == target - numbers[i])
42         {
43             if (index[i] < index[indexLook])
44             {
45                 ans[0] = index[i]+1;
46                 ans[1] = index[indexLook]+1;
47             }
48             else
49             {
50                 ans[1] = index[i]+1;
51                 ans[0] = index[indexLook]+1;
52             }
53             return ans;
54         }
55     }
56 }

这里,还有一种也比较常规的解法:HashTable。(O(n))

可以在边建立哈希表的同时也进行查找(按先后顺序,查找第二个时第一个肯定已经入表)。将num中的值映射到其下标,对于每一个num中的值e,在HashTable中查找target-e对应的下标。如果能找到直接返回结果;如果不能找到则把e和其下标也加入哈希表中。

Java解法如下:

 1 import java.util.HashMap;
 2 import java.util.Map;
 3
 4 public class Solution {
 5     public int[] twoSum(int[] numbers, int target) {
 6         Map<Integer, Integer> map=new HashMap<>(numbers.length*2);
 7         for(int i=0;i<numbers.length;i++){
 8             Integer company=map.get(target-numbers[i]);
 9             if(company==null)
10                 map.put(numbers[i], i);
11             else
12                 return new int[]{company+1,i+1};
13         }
14         return null;
15     }
16 }

另外,其实这道题的本质就是找one pair numbers使得其和等于target。我们可以从整体上来看待这个问题,并且根据找到的pair与target之间的关系调整位置继续找,直到找到符合条件的唯一解。

当num排完序后,我们考虑从第一个数(i=0)和最后一个数(j=len-1)开始,如果它们的和比target大,说明此时和需要调整得更小,那么把j指针向前调;如果当前的和比target小,则把i指针向后调。直到找到这样的pair使得和正好等于target。这样就可以避免对于每一个元素e都要对target-e进行二分查找,效率肯定更高。(因为如果当前i一定是最后结果(i, j)中的一个值,那么比当前j下标大的数一定使得当前和比target大,所以j会不断减小直到到正确解,正确性可以得到证明。)

AC代码如下(Python):O(nlogn)

 1 class Solution:
 2     # @return a tuple, (index1, index2)
 3     def twoSum(self, num, target):
 4         copyNum = num[:]
 5         copyNum.sort()
 6         firstIndex = 0
 7         lastIndex = len(copyNum) - 1
 8         while True:
 9             if copyNum[firstIndex] + copyNum[lastIndex] == target:
10                 break
11             elif copyNum[firstIndex] + copyNum[lastIndex] > target:
12                 lastIndex -= 1
13             else:
14                 firstIndex += 1
15
16         fIndex = num.index(copyNum[firstIndex])+1
17         num.reverse()
18         lIndex = len(num) - num.index(copyNum[lastIndex])
19
20         if fIndex > lIndex:
21             fIndex, lIndex = lIndex, fIndex
22         return (fIndex, lIndex)
23         

(因为index只能找到第一个等于该值得下标,当两个加数相等时,就必需从后往前找,所以要num.reverse(),或者自己写一个function从后往前找。)

参考:

1、https://leetcode.com/discuss/27316/java-solution-space-using-binarysearch-time-space-using-hash

2、https://leetcode.com/discuss/26760/python-solution-with-52ms-cost

时间: 2024-08-05 01:05:15

【LeetCode】Two Sum的相关文章

【Leetcode】Path Sum II

Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. For example: Given the below binary tree and sum = 22, 5 / 4 8 / / 11 13 4 / \ / 7 2 5 1 return [ [5,4,11,2], [5,8,4,5] ] 思路:与[Leetcode]Path Sum 不同

【LeetCode】- Two Sum(两数相加)

[ 问题: ] 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 no

【LeetCode】Path Sum

题目 Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. For example: Given the below binary tree and sum = 22, 5 / 4 8 / / 11 13 4 / \ 7 2 1 return true,

【LeetCode】Combination Sum I &amp; II 解题报告

[Combination Sum I] Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. The same repeated number may be chosen from C unlimited number of times. Note: All numbers (inc

【LeetCode】Path Sum II 解题报告

[题目] Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. For example: Given the below binary tree and sum = 22, 5 / 4 8 / / 11 13 4 / \ / 7 2 5 1 return [ [5,4,11,2], [5,8,4,5] ] [解析] DFS,递归实现. /** *

【Leetcode】Range Sum Query 2D - Immutable

题目链接:https://leetcode.com/problems/range-sum-query-2d-immutable/ 题目: Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2). The above rectangle (w

【leetcode】Combination Sum

Combination Sum Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. The same repeated number may be chosen from C unlimited number of times. Note: All numbers (includi

【leetcode】371. Sum of Two Integers

题目描述: Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. 解题分析: 这种类型的题必然要用位运算,虽然自己写了关于位运算的代码,但是不够简洁. 后来参考了这篇博文: http://blog.csdn.net/zhongjiekangping/article/details/6855864 这篇博文对位运算加法的实现讲的得十分清楚,我这里就只放按此思路写

【leetcode】Combination Sum II

Combination Sum II Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. Each number in C may only be used once in the combination. Note: All numbers (including t