1. 程式人生 > >56 兩數之和

56 兩數之和

暴力 運行 個數 sof fin 根據 html AC text

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

給一個整數數組,找到兩個數使得他們的和等於一個給定的數 target

你需要實現的函數twoSum需要返回這兩個數的下標, 並且第一個下標小於第二個下標。註意這裏下標的範圍是 0 到 n-1

註意事項

你可以假設只有一組答案。

您在真實的面試中是否遇到過這個題? Yes 樣例

給出 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
標簽 排序 哈希表 愛彼迎 數組 臉書 兩根指針 微軟亞馬遜 Bloomberg 優步 領英 蘋果 Yelp 雅虎Adobe 掉盒子 方法一: 雙重循環暴力查找……我知道會被鄙視,但菜鳥第一反應就是這個,哭唧唧 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中兩個數據。

56 兩數之和