LeetCode總結,leetcode

來源:互聯網
上載者:User

LeetCode總結,leetcode
這篇文章的主題是動態規劃, 主要介紹LeetCode中一維動態規劃的題目, 列表如下: 
Climbing Stairs
Decode Ways
Unique Binary Search Trees
Maximum Subarray
Best Time to Buy and Sell Stock

在介紹上述具體題目之前, 我們先說說動態規劃的通常思路。 動態規劃是一種演算法思路(注意這裡不要和遞迴混淆, 事實上遞迴和迭代只是兩種不同的實現方法, 並不是演算法), 用一句話來總結就是, 動態規劃是利用儲存曆史資訊使得未來需要曆史資訊時不需要重新計 算, 從而達到降低時間複雜度, 用空間複雜度換取時間複雜度目的的方法。 我個人喜歡把動態規劃分為以下幾步: 
1) 確定遞推量。 這一步需要確定遞推過程中要保留的曆史資訊數量和具體含義, 同時也會定下動態規劃的維度; 
2) 推導遞推式。 根據確定的遞推量, 得到如何利用儲存的曆史資訊在有效時間(通常是常量或者線性時間)內得到當前的資訊結果; 
3) 計算初始條件。 有了遞推式之後, 我們只需要計算初始條件, 就可以根據遞推式得到我們想要的結果了。 通常初始條件都是比較簡單的情況, 一般來說直接賦值即可; 
4) (可選)考慮儲存曆史資訊的空間維度。 這一步是基於對演算法最佳化的考慮, 一般來說幾維動態規劃我們就用幾維的儲存空間是肯定可以實現的。 但是有時我們對於曆史資訊的要求不高, 比如這一步只需要用到上一步的曆史資訊, 而不需要更早的了, 那麼我們可以只儲存每一步的曆史資訊, 每步覆蓋上一步的資訊, 這樣便可以少一維的儲存空間, 從而最佳化演算法的空間複雜度。 
動態規劃的時間複雜度是O((維度)×(每步擷取當前值所用的時間複雜度))。 基本上按照上面的思路, 動態規劃的題目都可以解決, 不過最難的一般是在確定遞推量, 一個好的遞推量可以使得動態規劃的時間複雜度盡量低。 

接下來我們來看看具體題目, 一維動態規劃的題目主要分成兩類: 

(1) 第一種是比較簡單的, 直接地按照上面步驟就可以解出來的, 確定遞迴量, 然後按遞迴式迭代就可以得到。 這種類型的題目是: Climbing Stairs,Decode Ways和Unique Binary Search Trees。 
Climbing Stairs中遞推量很清晰, 就是爬到i級樓梯有多少種可行爬法。 而對於遞推式我們可以看出, 要到達i級樓梯, 必須通過i-1級或者i-2級(以為只能爬一級或者兩級), 如此可以得到到達i級樓梯的方式有f(i)=f(i-1)+f(i-2)種, 這樣遞推式也就出來了。 而初始條件則是一級樓梯是一種解法, 兩級樓梯是兩種解法(2或者11)。 有了這些接下來遞推到n級樓梯返回即可, 空間複雜度是O(n)(一維動態規劃乘以每一步的常量操作)。 空間上我們發現每一步,只需要前兩步的曆史資訊, 所以我們不需要儲存所有曆史資訊, 只需要儲存前兩步, 然後迭代替換就可以了, 所以空間複雜度是O(2)=O(1), 這裡對應於上面的第四步。 
Decode Ways中遞推量也是類似的到達第i個字元可解析方式的數量, 遞推式比Climbing Stairs稍微複雜一些, 要分情況討論, 主要對於自己和前面一位組成數位不同要分別處理一下, 這裡就不列出來的,大家可以看看Decode Ways -- LeetCode。 雖然是分情況,不過每種情況也是可以常量時間更新資訊的, 初始條件依然是非常簡單的case, 空間上也是只需要儲存前兩步的資訊, 所以時間和空間複雜度跟Climbing Stairs都是一樣的。 
Unique Binary Search Trees思路還是類似的, 遞推式是稍有不同, 按左右子樹劃分然後進行累加, 最後歸結為卡特蘭數的模型。 這個問題仍然是一維動態規劃, 但是求解單步資訊時是一個線性操作, 所以時間複雜度是O(n^2)。 而空間上因為每一步都需要前面每一步的所有資訊, 所以也無法最佳化, 是O(n)。 

(2) 接下來我們介紹第二種類型, 雖然也是一維動態規劃, 但是區別在於這類題目需要維護兩個遞推量, 所以思路上有一點技巧。 不過還是比較有通法的, 我通常把這種方法稱為”局部最優和全域最優解法“。 這種方法中我們通常維護兩個量, 一個是到目前為止最好的結果資訊(全域最優), 另一個必須包含新加進來的元素的最好的結果資訊(局部最優), 然後還是推導遞推式, 計算初始條件, 跟動態規劃的通常思路一樣了。 Maximum Subarray和Best Time to Buy and Sell Stock就是這種類型的題目。 
Maximum Subarray中對於遞推量我們維護兩個,一個是到目前為止最好的子數組, 而另一個量則是加入當前元素之後, 包含當前元素的最好的子數組, 最終我們是看全域最優的變數的最優值, 而局部最優卻是我們在遞推過程中維護全域最優所需要的。 遞推式還是有點技巧, 第i+1步運算式如下: 
  local[i+1]=Math.max(A[i], local[i]+A[i]),就是局部最優是一定要包含當前元素,所以不然就是上 一步的局部最優local[i]+當前元素A[i](因為local[i]一定包含第i個元素,所以不違反條件),但是如果local[i]是負的,那麼加上他就不如不需要的,所以不然就是直接用A[i]; 
  global[i+1]=Math(local[i+1],global[i]),有了當前一步的局部最優,那麼全域最優就是當前的局部最優或者還是原來的全域最優(所有情況都會被涵蓋進來,因為最優的解如果不包含當前元素,那麼前面會被維護在全域最優裡面,如果包含當前元素,那麼就是這個局部最優)。 
初始條件都是0或者第一個元素既可以了, 一遍掃過來, 每次迭代更新兩個量(都是常量時間), 所以時間是O(n)。 空間上可以看出只需要上一步的資訊, 所以只需要儲存上一步的全域最優和局部最優即可, 複雜度是O(2)=O(1)。 
Best Time to Buy and Sell Stock跟Maximum Subarray是完全一樣的, 也是維護兩個量, 一個是到目前為止最好的交易(全域最優), 另一個是在當前一天賣出的最佳交易(局部最優), 其他步驟也是一樣的, 這裡就不列出來了。 

可以看出, 上面五道一維動態規劃的題目都是按照我前面列出的四個步驟進行求解的, 事實上所有動態規劃題目都是按照這個基本思路來的。 掌握了套路之後就是看對具體問題要維護的遞推量的選擇了,這個個人感覺還是比較靠經驗的, 熟能生巧。
leetcode是什

裡面有很編程多面試的題目,可以線上編譯運行。難度比較高。如果自己能都做出來,對面大公司很有協助。我就是做的那裡的題目。
 
什叫部落格

blog的全名應該是Web log,中文意思是“部落格”,後來縮寫為Blog,而部落格(Blogger)就是寫Blog的人。從理解上講,部落格是“一種表達個人思想、網路連結、內容,按照時間順序排列,並且不斷更新的出版方式”。簡單的說部落格是一類人,這類人習慣於在網上寫日記。
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.