56 兩數之和
原題網址: 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
1 class Solution { 2 public: 3 /** 4 * @param numbers: An array of Integer5 * @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 intsize=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 兩數之和