求兩個數之和。這個問題夠簡單吧!能做對絕對不是問題,問題是你是否能做的比較好。好了,請看題目:
Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
看了題目之后,心中是否已經有了答案。很簡單蠻力法嘛,一個雙循環就可以搞定了。但是有沒有更好一點的方法呢?
如果你已經想到了也沒必要往下看了。
如果你還沒有什么頭緒,那么稍微往HashTable想想,估計你們也想到了。其實也是很簡單,只是有時候想問題的方向不對,就老是想不到點子上罷了。如果還沒想到的話,就往下看一下吧!
相比較於,用一個雙循環,在時間效率上面可能不是很好。那么久可以很容易想到,也經常聽到的“空間換時間”,就是這樣,我們可以使用一個字典鍵值對保存中間值,減少一次循環,變成單循環,那么時間效率就可以得以提升。
那么這個字典到底保存什么呢?保存目標值減去當前數組的整數值(鍵)和數組整數值的下標(值)。當我們執行循環時,每循環到一個數組中的整數,我們就判斷這個整數是否是字典中的鍵,如果不是我們就按照前面說的鍵值存入字典中,題目說了有且只有一對數字是符合條件的,那么也就不用考慮重復鍵了。如果是,我們就找到了這兩個整數,接着就是返回整兩個整數的下標了。第一個整數的下標就是當前字典的鍵對應的值,第二個整數的下標就是當前循環到的i值。就是這么簡單!如果我說的不夠清楚就直接看代碼。
以下是C#的實現:
1 using System; 2 using System.Collections.Generic; 3
4 namespace XiaoLiang 5 { 6 public class TwoSum 7 { 8 public int[] TwoSum(int[] nums, int target) 9 { 10 int[] result = new int[2]; 11 Dictionary<int, int> dictionary = new Dictionary<int, int>(); 12 for (int i = 0; i < nums.Length; i ++ ) 13 { 14 if(dictionary.ContainsKey(nums[i])) 15 { 16 result[0] = dictionary[nums[i]]; 17 result[1] = i; 18 return result; 19 } 20 else
21 { 22 dictionary.Add(target - nums[i] , i); 23 } 24 } 25 return result; 26 } 27 } 28
以下是C++的實現:
1 class Solution { 2 public: 3 vector<int> twoSum(vector<int>& nums, int target) { 4 int i = 0, n = nums.size(); 5 unordered_map<int, int> m; 6 vector<int> ret; 7
8 for (i = 0; i < n; ++i) 9 { 10 if (m.find(target - nums[i]) != m.end()) 11 { 12 ret.push_back(m[target - nums[i]]); 13 ret.push_back(i); 14 break; 15 } 16 m[nums[i]] = i; 17 } 18
19 return ret; 20 } 21 };
如果有什么說的不對的地方歡迎拍磚,有更好的方法可以共享。