1. 程式人生 > 實用技巧 >動態規劃面試題型歸類機

動態規劃面試題型歸類機

1. 路徑數目問題

  • 1.1. 一維路徑數目
題目概述
一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(先後次序不同算不同的結果)。

解法
第一步找到適用於該題的狀態表示,這裡把狀態函式設定為f(n),即跳了n個臺階的跳法總數。現在需要通過先前的資訊推導f(n),假設青蛙跳了n格,如果它是1跳到n格的,那麼一共f(n-1)種跳法;如果是2跳到n格的,那麼一共f(n-2)種跳法,所以一共有f(n-1)+f(n-2)種跳法。

\[f(n)= \begin{cases} 1 & n=1 \\ 2 & n=2 \\ f(n-1) + f(n-2) & n>2 \end{cases} \]

  • 1.2. 二維路徑數目
題目概述
有一個障礙表(二維陣列),1表示有障礙不能走,0可以走,只能向右一格或向下一格走
找到從左上角到右下角一共的路徑數目
def uniquePathsWithObstacles(self, obstacleGrid):
    # type obstacleGrid: List[List[int]]
    row = len(obstacleGrid)
    col = len(obstacleGrid[0])
    dp = [[1] * col for i in range(row)]
    for i in range(0, row):
        for j in range(0, col):
            if obstacleGrid[i][j]: # 如果這個點是障礙
                dp[i][j] = 0
            elif i == 0:
                dp[i][j] = dp[i][j-1]
            elif j == 0:
                dp[i][j] = dp[i-1][j]
            else:
                dp[i][j] = dp[i-1][j] + dp[i][j-1]
    return dp[-1][-1]
  • 1.3. 串路徑數目
題目概述
'A'到'Z'用數字1~26表示
Input: "12"
Output: 2
12可以有兩種編碼方式 "AB" (1 2) or "L" (12).

解法
相當於從字串首到尾找路徑數目
def numDecodings(self, s):
    if len(s)==0 or s[0]=='0': return 0
    dp = [1,1]
    for i in range(2, len(s)+1):
        if s[i-2:i]=='10' or s[i-2:i]=='20':
            dp.append(dp[i-2])
        elif 10<int(s[i-2:i])<=26:
            dp.append(dp[i-1]+dp[i-2])
        elif s[i-1]!='0':
            dp.append(dp[i-1])
        else:
            return 0
    return dp[-1]

2. 路徑耗費問題

  • 2.1. 二維路徑耗費
題目概述
非負二維陣列,找到從左上角到右下角的路徑,使元素和最小的那個最小值
只能向右一格或向下一格走

解法
設定狀態dp[row][col]表示從左上角走到row行col列元素和最小的路徑的元素和大小

\[dp[row][col] = min(dp[row][col-1], dp[row-1][col]) + matrix[row][col] \]

題目概述
[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]
給以上這種三角形,返回從頂到底的元素和最小走法(每次只能走鄰近子節點)
比如以上的結果:2 + 3 + 5 + 1 = 11

\[dp[row][i] = min(dp[row+1][i], dp[row+1][i+1]) + triagnle[row][i] \]

3. 數字拆分問題

  • 2.1. 求拆分數目
題目概述
Input: n = 13
Output: 2
Explanation: 13 = 4 + 9.
輸入一個正整數n, 輸出其最少能由幾個完全平方數相加組成(完全平方數為1,4,9,16,...)

解法:

\[dp[n] = min(dp[n-s]+1), \ \ s \in 1,4,9,16,... \]

int numSquares(int n) {
    int *dp = new int[n + 1];
    dp[0] = 0;
    for (int i=1; i<=n; i++) {
        int _min = INT_MAX;
        for (int j=1; j*j<=i; j++) {
            _min = min(_min, dp[i-j*j]+1);
        }
        dp[i] = _min;
    }
    delete[]dp;
    return dp[n];
}