日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

10.2 动态规划算法套路及空间优化 —— Climbing Stairs Unique Paths

發布時間:2024/1/18 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 10.2 动态规划算法套路及空间优化 —— Climbing Stairs Unique Paths 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這一篇文章從最簡單的動態規劃題目開始,結合上一節動態規劃三要素,以LeetCode兩道基礎的DP題目闡述DP問題的基本套路解法。


?

70.?Climbing Stairs

You are climbing a stair case. It takes?n?steps to reach to the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

Note:?Given?n?will be a positive integer.

?

題目解析:

這是一道最基礎的動態規劃問題,用于我們初步了解。首先我們來回憶DP三大要素,抽煙喝酒燙頭,不,是最優子結構,狀態轉移方程和邊界。

  • ?最優子結構,就是分析問題的關鍵,構建解題框架。之前以斐波那契數列為例,這次我們以這道題目為例。想知道到達n層臺階,有多少種方式,即f(n)是最終想要的答案,抽象為f(i) 即到達任何一層臺階的方式;所謂子結構,即f(i-1),f(i-2),f(i-3),...,f(2),f(1)。很明顯,f(i)的方案數目和?f(i-1)等子問題的答案是有關系的。這就是第一步分析問題我們要做的。
  • 狀態轉移方程。f(i)和子問題具體是什么關系呢?這一步要定量分析。由于每次只能走一步或兩步,一步之前的臺階在i-1層,兩步之前在i-2層,那么第i層的方案數目不就是:f(i) =?f(i-1) +?f(i-2),(還是斐波那契數列)。這一步定量分析問題和子問題之間的數量關系,
  • 邊界。到這兒就很好理解了,可以定義 f(1)=1, f(2)=2.
  • 其實還有第四步,就是編碼啦,能把你的思路寫出來才行。
  • 下面我們看代碼實現,在dp問題中,對于f(i)我們一般存為數組dp.

    class Solution:def climbStairs(self, n: int) -> int:# 特殊情況if n <= 2:return n# dp數組必備dp = [0] * (n+1)# 邊界dp[1] = 1dp[2] = 2for i in range(3, n+1):# 狀態轉移方程dp[i] = dp[i-1] + dp[i-2]return dp[-1]

    ?

    這個一維的問題就圖森破了,下面我們看經典的二維dp問題。說來說去,二維不一定比一維的就難,一維的數組也有很多難題。

    62.?Unique Paths

    A robot is located at the top-left corner of a?m?x?n?grid (marked 'Start' in the diagram below).

    The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

    How many possible unique paths are there?

    ?

    題目解析:

    我們仿照上題的思路來解析,看三大要素。f(i,j)表示到達i行j列的路徑數,f(m,n)即最終結果。i行j列是從左側或上邊走過來的,必然有一定的最優子結構的形式。那么接下來分析狀態轉移方程。和上一題類似,i行j列的上一步或者在i-1行j列,或者在i行j-1列,只有這兩種情況,且每種情況下只有一條路徑到i,j,因此直接得到f(i,j) = f(i-1,j) + f(i,j-1)。二維問題的邊界也在二維數組的邊界,下面我們直接看代碼實現:

    class Solution:def uniquePaths(self, m: int, n: int) -> int:# dp數組dp = [[0] * n for _ in range(m)]# 邊界for i in range(m):dp[i][0] = 1for i in range(n):dp[0][i] = 1for i in range(1, m): for j in range(1, n):# 狀態轉移方程dp[i][j] = dp[i-1][j] + dp[i][j-1]return dp[m-1][n-1] # 或dp[-1][-1]

    再額外解釋一下邊界,沿著第一行或者第一列都是只有一種路徑,所以邊界的初始值都是1,也可以直接把dp數組初始化為1.


    先充分的消化一下上面兩道問題的dp套路,從三要素理解解題思路,進而理解dp的核心思想,最優子結構和無后效性。

    根據無后效性,下面我們看一下dp算法的優化思路。

    以climbing stairs為例,基本思路中我們定義了長度為n的數組用于存儲i處的最終解,時間復雜度O(n);但是從關系式dp[i] = dp[i-1] + dp[i-2]可以看出,在i處我們只需要i-1和i-2的值,更早的值我們不需要了,這就體現了無后效性,因此我們只需要三個變量即可解決問題,下面看代碼:

    class Solution:def climbStairs(self, n: int) -> int:if n <= 2:return npre1 = 2pre2 = 1dp = 0for i in range(3, n+1): dp = pre1 + pre2pre2, pre1 = pre1, dpreturn dp

    就是這樣,將空間復雜度降到了O(1)。我們再看unique paths題目的優化。

    對于第i行第j列,我們看關系式 f(i,j) = f(i-1,j) + f(i,j-1),在前面的解法中,我們的空間復雜度是O(m*n),對于每個位置來說,我們需要左邊的和上邊的,對于每一行來說,我們只需要上一行的結果即可。因此我們可以將空間復雜度降到O(n),結合下面代碼來看,我們只定義一個一維dp數組,在每行遍歷中,不斷更新dp數組的值,不斷拋棄上一行的結果,直到最后一行。

    class Solution:def uniquePaths(self, m: int, n: int) -> int:# 定義一維dp數組,同時初始化了第一行的邊界值dp = [1] * nfor i in range(1, m): for j in range(n):# 第一列的邊界if j == 0:dp[j] = 1else:# 相當于原狀態轉移方程,不斷更新dp數組值dp[j] += dp[j-1]return dp[-1]

    ?

    總結

    以上是生活随笔為你收集整理的10.2 动态规划算法套路及空间优化 —— Climbing Stairs Unique Paths的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。