python leetcode 之兩數之和(two sum)

王平發表於2019-03-13

Leetcode,這個大名鼎鼎的刷題神器,對於將要入行碼農行業或已是碼農的猿猿們來說,是必不可少的的練習工具。但可能還有很多小猿們還不知道它。從今天起,我將寫一個【Leetcode的刷題練Python】的系列,和大家一起用Python來解Leetcode的上面的演算法題目。

Leetcode是什麼?

它是一個美國的線上程式設計網站。官方網址是:http://leetcode.com/,開啟瀏覽器輸入網址,就可以線上寫程式碼、提交、檢視演算法的優略以及個人別實現演算法的對比等等。開箱即用,非常方便。

上面收錄的演算法題目,大多來自大公司的筆試面試題,分為簡單、中等、困難三個等級,從基礎到高階都有。是學習演算法練習程式設計準備筆試面試的必備良器。不要遲疑,馬上和我開始刷題之旅吧!

如何使用Leetcode?

Leetcode既然是美國的,自然網站語言也是英文的。但它出了正文版,且用了獨立域名: https://leetcode-cn.com/ 。中文的題目描述可能更方便我們理解,英文版同時也練練我們的專業英語。具體選用什麼語言各選所好,題目的編號都是對應的,也方便大家中文對照著看。我寫這個系列就選中文吧。

簡單註冊登入,或用github等第三方賬戶登入,就可以看到下面的介面:

LeetCode介面

題目分“演算法”,“資料庫”和“shell”指令碼三種,其中演算法已經有840個題目,足夠你過刷題的癮了。

點選題名就進入刷題頁面:

LeetCode兩數之和

如果你看不懂中文,可以“切換為英文”;

如果你沒有思路,可以看看“評論”,或者看看“題解”;

如果你想用C++、Python、Java都實現一遍,可以選擇不同程式語言;

讀懂了左邊的題目,就可以在右邊的編輯框寫程式碼了;

寫完程式碼,先“執行程式碼”看看有沒有錯;

如果沒有錯誤,就可以“提交”了,提交完就能看到是否全部測試都透過,已經用時、耗費的空間、超過了百分之幾的其他人等資訊,這是對你演算法實現的評價,不滿意就再修改演算法再次提交。

基本的使用就是這些。接下來正式刷題。

題目:兩數之和

  1. 題目描述

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

你可以假設每種輸入只會對應一個答案。但是,你不能重複利用這個陣列中同樣的元素。

示例:

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

因為 nums[0] + nums[1] = 2 + 7 = 9

所以返回 [0, 1]

2. 解題思路和Python知識點

這個題目主要考察我們如何遍歷陣列(Python的列表),從中找出想要的元素。

最原始的方法就是,從頭到尾,對每個元素找它後面的每一個元素是否與它匹配(也就是兩者的和為target)。用兩個巢狀的迴圈來實現,思路很正常,但是效率最低:

時間複雜度是O(n2),空間複雜度是O(1)

好處是基本不消耗記憶體。

不妨實現一下這個方法,看看能跑出怎樣的結果:

兩數之和得分情況

果不其然,提交後得到這樣的令人鄙視的結果:

兩數之和簡單版的得分情況

拿這樣的演算法去面試是找不到工作的!

進一步,我們想到演算法無非是“以時間換空間,以空間換時間”。馬兒要想跑得快,就得吃得多。每次我們遍歷到某一元素時,它前面的若是已經記錄下來,可能就不需要多一個巢狀的迴圈了。那麼,問題就變成如何記錄下來,讓它比一個巢狀的迴圈速度快(耗時少)?

想想Python的資料結構中,列表、tuple和字典,那個查詢速度快呢?顯然是字典(據說,字典的查詢速度平均是O(1),最壞情況是O(n))。好,那麼就用字典來儲存已經遍歷的元素,再查詢target與當前元素的差是否在字典中即可,那麼它的實現就是:

兩數之和簡單版解題思路

這結果比上個快了100多倍,但似乎也不能讓人十分滿意:

兩數之和最佳化後的得分情況

看這個結果,也就是說有三分之一的Python3提交比這個速度快。Python如何實現更高效的演算法呢?留給大家作為討論話題,大家有什麼思路留言討論吧。

 

猿人學banner宣傳圖

我的公眾號:猿人學 Python 上會分享更多心得體會,敬請關注。

***版權申明:若沒有特殊說明,文章皆是猿人學 yuanrenxue.com 原創,沒有猿人學授權,請勿以任何形式轉載。***

相關文章