LeetCode修仙:Two Sum詳解

不重要:

最近天天玩吃雞,優點頹廢,好好堅持刷一下LeetCode,本博客力求一題多解,從時間複雜度上完成自我代碼修養的提高。

problem:

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, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].


方法1:

分析:

首先我們知道:無需把數組中所有的符合要求的下標組列出來,只需要一組,並且與順序無關。我們很容易想到一種思路如下圖:


我們可以從第一個藍色開始:一個一個跟後面的比對;繼而黃色;以此類推...發現有數據對滿足和爲:target.就結束尋找;並返回兩者下標;


代碼如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
      vector<int> answer;
      int len=(int)nums.size();
      for(int i=0;i<len-1;i++)  
          for(int j=i+1;j<len;j++) 
          {
              if((nums[i]+nums[j])==target)
              { 
                  answer.insert(answer.end(), i);
                  answer.insert(answer.end(), j);
                  break;
              }
          }
       return answer;
    }
};

運行效果:


可能錯誤:

reference binding to null pointer of type 'value_type'
注意:vector的賦值分兩個,一者在初始化的時候;一者在後續插入。由於代碼中answer的初始化未進行,所以,如果用

                  answer[0]=i;
                  answer[1]=j;

替換

                  answer.insert(answer.end(), i);
                  answer.insert(answer.end(), j);

則會出現上述錯誤;


方法2:

上述的方法雖然可以通過,但是我們不難發現,時間成本還是比較高,時間複雜度是O(N^2),顯然不是最優秀的解法,於是,上網搜索更好的思路發現了新大陸:hash_map,通過這種Key+value的快速搜索結構體,我們可以進一步加快我們的程序;

新版的C++ 11中hash_map都是unordered_map了,所以這裏只說unordered_map,但也要區分它和map的區別:

運行效率方面:unordered_map最高,而map效率較低但 提供了穩定效率和有序的序列。

佔用內存方面:map內存佔用略低,unordered_map內存佔用略高,而且是線性成比例的。


unordered_map的用法:


開頭:

     #include<tr1/unordered_map>//加上tr1庫名,
     using namespace std::tr1;//加上命名空間


初始化:

unorder_map<int, string> mapStudent;  
mapStudent[1] =  “student_one”;
mapStudent[2] =  “student_two”;
mapStudent[3] =  “student_three”;

查找:
    若有unordered_map<int, int> mp;查找x是否在map中
    方法1:  若存在  mp.find(x)!=mp.end()
    方法2:  若存在  mp.count(x)!=0

插入:

map.insert(map::value_type(1,"Raoul"));


遍歷:

       unordered_map<int, string>::iterator  iter;map<int, string>::iterator  iter;
       for(iter = mapStudent.begin();  iter != mapStudent.end();  iter++)

         {...}


利用Value查找Key&&刪除:

       map<int, string>::iterator iter;

       iter = mapStudent.find(1);

       mapStudent.erase(iter);


代碼如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
      vector<int> answer;
      unordered_map<int,int> hash;
      for(int i=0; i<nums.size(); i++)
      {
          int NumToFind=target-nums[i];
          if(hash.find(NumToFind) != hash.end())
          {
              answer.push_back(hash[NumToFind]);
              answer.push_back(i);
              return answer;
              break;
          }
          else
              hash[nums[i]]=i;
      }
    }
};


代碼註解:

你可能覺得hash對象並沒有被初始化:這不是問題:因爲這裏比較巧妙,hash一開始確實是空的:不過在每一次循環中,最後都會執行:

hash[nums[i]]=i;
所以hash是從頭部開始進入的:比如:【2,6,9,8,3,4】target=5
最後輸出的是第五層for循環中(i=4),發現NumToFind=5-3=2時候,從hash中找到了2,這樣得出來的,這也解釋了answer中爲什麼先push進去的不是i;所以這裏有點巧妙,也可以說:有點難理解,是一個“反哺”的機制,挺有意思的;


運行結果:


總結:

這樣,時間從189ms提高到了9ms,十分滿足,而且也順便學了unordered_map的用法。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章