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<int, int> 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的正確方式