LeetCode 熱題 HOT 100(00,兩數之和)

LeetCode 熱題 HOT 100(00,兩數之和)

不夠優秀,髮量尚多,千錘百煉,方可成佛。

算法的重要性不言而喻,無論你是研究者,還是最近比較火熱的IT 打工人,都理應需要一定的算法能力,這也是面試的必備環節,算法功底的展示往往能讓面試官眼前一亮,這也是在大多數競爭者中脫穎而出的重要影響因素。

然而往往大多數人比較注重自身的實操能力,着重於對功能的實現,卻忽視了對算法能力的提高。有的時候採用不同的算法來解決同一個問題,運行效率相差還是挺大的,畢竟我們最終還是需要站在客戶的角度思考問題嘛,能給用戶帶來更加極致的體驗當然再好不過了。

萬法皆空,因果不空。Taoye之前也不怎麼情願花費太多的時間放在算法上,算法功底也是相當的薄弱。這不,進入到了一個新的學習階段,面對導師的各種“嚴刑拷打”和與身邊人的對比,才意識到自己“菜”的事實。

步入11月,也開學一個多月了,所以想開始記錄下刷算法題的過程,也算是對自己的一個督促。初步的目標是一到兩天更新一期,每週至少更新四期。

題目:兩數之和

給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們的數組下標。

你可以假設每種輸入只會對應一個答案。但是,數組中同一個元素不能使用兩遍。

示例

給定 nums = [2, 7, 11, 15], target = 9

因爲 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

思路

這是LeetCode 熱題 HOT 100中的第一道題,難度級別屬於簡單,也是每一位刷題er的入門必經之題,它的地位就等同於英語單詞表中的abandon,算法記錄的第一天就拿它開刀吧。

按照對這道題的正常思維,直接通過兩層循環、一次判斷就能完成任務,也就是我們常常提到的暴力解題,相關Python代碼如下:

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        # 兩層循環
        for index_1, num_1 in enumerate(nums):
            for index_2, num_2 in enumerate(nums):
                # 一次判斷
                if (num_1 + num_2) == target and index_1 != index_2:
                    return [index_1, index_2]
        return []

但是,要想有效提高自己的算法能力,還是有必要培養自己的“不正常”思維的。毫無疑問,上述暴力破解自然能夠滿足題意的要求,但在我們的業務功能已經全部實現的情況下,就不得不考慮代碼的執行效率問題了,這也就凸顯出了算法的重要性。

暴力解題的時間複雜度爲,空間複雜度爲。但我們可以通過哈希表(key-value鍵值對)來降低算法的時間複雜度。

對於遍歷的每一個,我們都計算其對應的的值,判斷值是否在哈希表中,如果在的話說明已經匹配成功,直接返回值對應的索引。反之,我們需要將當前遍歷的添加到哈希表中,x列表中所對應的索引。

如此一來,最多隻需要遍歷一次列表即可查找到目標值的索引,其時間複雜度爲,空間複雜度爲。相對於暴力解題來講,採用的是以空間換時間的策略。

在計算機發展初期,內存是極爲奢侈的,內存的使用都是要經過慎重考慮的。而在今日,曾今的內存問題已經不再是問題了,有的時候,站在客戶的角度來講,我們通常會情願採用以空間換時間的策略。

代碼實現

  • Python
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashtable = dict()
        for index, num in enumerate(nums):
            if (target - num) in hashtable:     # 補集在哈希表中,直接返回目標索引
                return [hashtable.get(target - num), index]
            hashtable[num] = index              # 補集不在哈希表中,添加到hashtable
        return []
  • C++

官方

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<intint> hashtable;
        for (int i = 0; i < nums.size(); ++i) {
            auto it = hashtable.find(target - nums[i]);     // find查詢關鍵字,沒找到則返回end迭代器
            if (it != hashtable.end()) {                    // 如果找到了目標關鍵字
                return {it->second, i};                     // 返回索引
            }
            hashtable[nums[i]] = i;                         // 沒找到,則將關鍵字添加到hashtable
        }
        return {};
    }
};

在C++中,通過hashtable作爲底層實現的主要有兩個容器

  • unordered_set,就是一個單類型數據的set集合,內部的元素不能重複,比如名字set集合,name_set={"taoye", "taotao"}
  • unordered_map,一個key-value鍵值對型的容器,比如id、姓名類型的map,info_map={1: "taoye", 2: "taotao"}
// 在unordered_map中,find用於進行關鍵字的查詢,找到則返回指向關鍵字的迭代器,否則返回指向end的迭代器
iterator find (const key_type& k);

我是Taoye,研究生在讀。愛專研,愛分享,熱衷於各種技術,學習之餘喜歡下象棋、聽音樂、聊動漫,希望藉此一畝三分地記錄自己的成長過程以及生活點滴,也希望能結實更多志同道合的圈內朋友,更多內容歡迎來訪微信公主號:玩世不恭的Coder

推薦閱讀:

Taoye滲透到一家黑平臺總部,背後的真相細思極恐
《大話數據庫》-SQL語句執行時,底層究竟做了什麼小動作?
那些年,我們玩過的Git,真香
基於Ubuntu+Python+Tensorflow+Jupyter notebook搭建深度學習環境
網絡爬蟲之頁面花式解析
手握手帶你瞭解Docker容器技術
一文詳解Hexo+Github小白建站
​打開ElasticSearch、kibana、logstash的正確方式

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