56 两数之和

原题网址: http://www.lintcode.com/zh-cn/problem/two-sum/#

给一个整数数组,找到两个数使得他们的和等于一个给定的数 target

你需要实现的函数twoSum需要返回这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 0 到 n-1

 注意事项

你可以假设只有一组答案。

样例

给出 numbers = [2, 7, 11, 15], target = 9, 返回 [0, 1].

挑战 

Either of the following solutions are acceptable:

  • O(n) Space, O(nlogn) Time
  • O(n) Space, O(n) Time
标签 
 
方法一:
双重循环暴力查找……我知道会被鄙视,但菜鸟第一反应就是这个,哭唧唧
PS:第一次敲代码时认为两数之和一定比两个加数都大所以排除了比target大的元素导致运行出错,负数表示我性别歧视……我……面壁去。
 
 1 class Solution {
 2 public:
 3     /**
 4      * @param numbers: An array of Integer
 5      * @param target: target = numbers[index1] + numbers[index2]
 6      * @return: [index1 + 1, index2 + 1] (index1 < index2)
 7      */
 8     vector<int> twoSum(vector<int> &numbers, int target) {
 9         // write your code here
10         vector<int> result;
11     int size=numbers.size();
12 
13     for (int i=0;i<size;i++)
14     {
15         
16         for (int j=i+1;j<size;j++)
17         {
18             
19             int sum=numbers[i]+numbers[j];
20             if (sum==target)
21             {
22                 result.push_back(i);
23                 result.push_back(j);
24                 return result;
25             }
26         }
27     }
28 
29     return result;    
30     }
31 };

挑战:

参考  https://www.cnblogs.com/eudiwffe/p/6282635.html

         https://www.cnblogs.com/libaoquan/p/6808064.html 

         C/C++——map的基本操作总结

         C++ map注意事项  count与find

常见的思路是:两层for循环,任意两个数组合求其和,判断是否等于给定的target。但这样太慢,需要O(n^2)的时间,O(1)的额外空间。可以反过来思考,假如当前选择了一个数字a,那么为了满足条件,另一个数字b必须满足:b=targe-a,即在数组中寻找是否存在b。

如何快速寻找数组中是否存在一个数字b?假如数组是有序的,可以使用二分查找方法,其查找时间复杂度是O(logn)。然而题目并没给定这个条件。如果对数组排序,首先就要O(nlogn)的时间进行排序,并且排序后,数字的原始下标也要保存,显然需要O(nlogn)的时间以及O(n)的空间,并不是最好的方法。

如何对一个数组进行快速查找一个元素?算法中提供了一种方法——哈希(Hash),即对数组中的每个元素按照某种方法(hash function)计算其“唯一”值id(称为哈希值),存储在新的数组A中(一般称为哈希数组),并且其下标就是这个“唯一”值。那么如果访问A[id]存在,则这个元素存在,否则,原始数组中不存在该元素。由于数组是顺序存储的支持随机访问所以查找一个元素是否在数组中,只需要O(1)的时间,但是在初始化哈希数组时,需要O(n)的时间和O(n)的空间。对于某些特定应用中,需要快速的时间,而对空间要求不苛刻时,哈希数组是一个非常好的方法。

 1 class Solution {
 2 public:
 3     /**
 4      * @param numbers: An array of Integer
 5      * @param target: target = numbers[index1] + numbers[index2]
 6      * @return: [index1 + 1, index2 + 1] (index1 < index2)
 7      */
 8     vector<int> twoSum(vector<int> &numbers, int target) {
 9         // write your code here
10         vector<int> result;
11     if (numbers.empty())
12     {
13         return result;
14     }
15     int size=numbers.size();
16     map<int,int> hashmap;
17 
18     for (int i=0;i<size;i++)
19     {
20         hashmap.insert(pair<int,int>(numbers[i],i));
21     }
22 
23     for (int i=0;i<size;i++)
24     {
25         int temp=target-numbers[i];
26         if (hashmap.count(temp)!=0&&hashmap[temp]!=i) //count查找元素出现次数,不为0说明存在;
27         {                                             //hashmap[temp]!=i防止target为某数组元素倍数时返回一样的下标值;
28             result.push_back(i);
29             result.push_back(hashmap[temp]);
30             break;
31         }
32     }
33     if (result[0]>result[1]) //保证当target为数组中两个等值元素的和时下标顺序从小到大;
34     {
35         int t=result[0];
36         result[0]=result[1];
37         result[1]=t;
38     }
39     return result;
40     }
41 };

简单解释下最后一个if语句:

第一次在lintcode上测试时,当数据为[0,3,4,0] 和 0 时输出[3 0],结果错误。

数组中出现两个相同元素值,下标分别为0、3,创建hashmap时,下标为3的0无法插入,所以hashmap中有三对pair,(0,0)(3,1)(4,2)

第二个for循环查找map时,由于target=0,temp=0,在hashmap中count(temp)为1,但hashmap[temp]为0,等于i,不满足要求,循环继续。

直到i=3,temp=0,查找hashmap,找到了key等于0的pair,即(0,0),将下标3、 0插入result中。根据题意,要交换result中两个数据。

 

 

 
posted @ 2018-04-06 20:23  eeeeeeee鹅  阅读(183)  评论(0编辑  收藏  举报