leetcode 動態規劃

2021-10-05 06:47:28 字數 3946 閱讀 9177

題目:給定乙個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。每次只能向下或者向右移動一步

示例:

輸入:[

[1,3,1],

[1,5,1],

[4,2,1]

]輸出: 7

解釋: 因為路徑 1→3→1→1→1 的總和最小。

思路:定義一維陣列dp用於記錄起始點到某一點最小距離,陣列長度為列長。除了dp[0]的值為0以外,其餘的都為最大值integer.max_value。

遍歷二維陣列:

1)在第一行(i = 0)中,起點到各個點的最短距離的方向就是一直往右走;

2)在第其他行(i > 0)中,由於只能往右或者下方向走,則起點到grid[i][0]的距離只能是一直往下;而對於其他列的點grid[i][j] (j > 0),則需要去比較上乙個節點dp[j - 1]與本節點dp[j]之間的大小,所謂的上個節點dp[j - 1]是指左邊的節點,而dp[j]]是指上邊的節點。

舉例說明:對於某一節點(2, 4),dp[3]是指起點到(2,3)的最小距離,而dp[4]是指起點到(1, 4)的最小距離。

public int minpathsum(int grid) 

dp[0] = 0;

for(int i = 0; i < row; i++) else }}

return dp[col - 1];

}

題目:給定乙個整數 n,求以 1 ... n 為節點組成的二叉搜尋樹有多少種?

示例:

輸入: 3

輸出: 5

解釋:給定 n = 3, 一共有 5 種不同結構的二叉搜尋樹:

思路:假設n個節點構成的搜尋樹個數為dp(n),以n為根節點的搜尋樹個數為f(n)。則可知:

1)dp[n] = f(1) + f(2) + f(3) + ... + f(n)        

2)當i為根節點時,左子樹節點為[1, i - 1],總共i - 1個節點;右子樹節點為[i + 1, n],總共n - i個節點。因此f(i) = dp(i - 1) * dp(n - i)。

由上面兩個式子可得:dp(n) = dp(0) * dp(n - 1) + dp(1) * dp(n - 2) + ... + dp(n - 1) * dp(0)。

舉例說明:當n=3時,dp(3) = dp(0) * dp(2) + dp(1) * dp(1) + dp(2) * dp(1)。即式子為dp(i) = dp(j) * (i - j - 1) 【j屬於[0, i)】

public int numtrees(int n) 

}return dp[n];

}

題目:給你乙個整數陣列 nums ,請你找出陣列中乘積最大的連續子陣列(該子陣列中至少包含乙個數字)。

示例1:

輸入: [2,3,-2,4]

輸出: 6

解釋: 子陣列 [2,3] 有最大乘積 6。

示例2:

輸入: [-2,0,-1]

輸出: 0

解釋: 結果不能為 2, 因為 [-2,-1] 不是子陣列。

思路

遍歷陣列,每個位置的最大連續子陣列的最大乘積有三種選擇:

(1)選擇自己本身nums[i];

(2)選擇本身與之前記錄的最大值相乘:curmax * nums[i];

(3)選擇本身與之前記錄的最小值相乘:curmin * nums[i],因為nums[i]可能為負數,與同樣可能為負數的curmin 相乘可能得到更大值。

public int maxproduct(int nums) 

return res;

}

乙個小偷計畫偷竊沿街的房屋。每間房內都藏有一定的現金,但相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。

給定乙個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下能夠偷竊到的最高金額。

示例 1:

輸入: [1,2,3,1]

輸出: 4

解釋: 偷竊 1 號房屋 (金額 = 1) ,然後偷竊 3 號房屋 (金額 = 3)。偷竊到的最高金額 = 1 + 3 = 4 。

思路:定義乙個陣列dp表示前i個房子中能搶到的最大現金:、

public int rob(int nums) 

return dp[length - 1];

}

題目:在乙個由 0 和 1 組成的二維矩陣內,找到只包含 1 的最大正方形,並返回其面積。

示例:

輸入

1 0 1 0 0

1 0 1 1 1

1 1 1 1 1

1 0 0 1 0

輸出:4

思路:假設定義乙個陣列dp[row][col],它表示以(i, j)為右下角所構成的最大正方形邊長。

(1)初始時,即i = 0或j = 0時,dp[i][j] = matrix[i][j] - '0'。在第一行或第一列的元素為右下角時,它們構成的正方形就是他們本身。

(2)對於其他行和列(i,j),若dp[i][j] = 1,則它們的值dp[i][j]依賴於它的上方(i,j - 1),它的左方(i - 1,j),它的左上方(i - 1,j - 1),若這三個值剛好相等,假設為x,那麼dp[i][j] = x + 1;若三個值不相等,那麼如果把三個正方形合起來,就會缺少某個角落,因此只能選三個中最小的那個,再加上1。

(3)最終得到的最大值maxcnt * maxcnt就是正方形面積。

上面我們定義的是二維陣列,同樣我們可以改為一維陣列dp[col]。每次遍歷時,我們用乙個變數topleft來記錄dp[j],這樣在當matrix[i][j]為1時,topleft表示的就是左上方或者左邊的值。

public int maximalsquare(char matrix) else 

maxcnt = math.max(dp[j], maxcnt);}}

return maxcnt * maxcnt;

}

題目:給定不同面額的硬幣 coins 和乙個總金額 amount。編寫乙個函式來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。

示例 1:

輸入: coins = [1, 2, 5], amount = 11

輸出: 3 

解釋: 11 = 5 + 5 + 1

示例 2:

輸入: coins = [2], amount = 3

輸出: -1

思路:定義陣列dp[amount + 1],dp[i]表示湊成金額i 所需的最少硬幣個數。遍歷所持有的硬幣值num,可以得出:

dp[i] = min(dp[i], dp[i - num] + 1

public int coinchange(int coins, int amount) }}

return dp[amount] == amount + 1 ? -1 : dp[amount];

}

leetcode 動態規劃

題目如下 給定乙個整型陣列,至少有乙個元素,請計算子陣列最大乘積是多少?子陣列必須是原陣列中連續的一串數字構成的陣列。整數可正可負。例如 給定陣列 2,3,2,4 經過計算,得到最大乘積為6。子陣列為 2,3 根據原貼的解題思路,這道題可以用動態規劃來解,但難度在 呢?負負得正,就可惡在這裡。那這個...

Leetcode 動態規劃

題目 原題鏈結在這裡 最長字串鏈。給乙個單詞列表,找乙個詞鏈,使得詞鏈後乙個單詞由前乙個單詞增加乙個字元得到,求最長詞鏈長度。解答 1 根據詞鏈的定義,短的單詞可以由長的單詞減去單詞中乙個字元得到。因此可以先對單詞列表,按照單詞的長度從大到小排序。2 單詞的最大長度為 16,因此可以對於每個單詞 w...

leetcode 動態規劃

3 動態規劃三要素 重疊子問題 最優子結構 狀態轉移方程 4 狀態轉移方程最難的 明確 狀態 定義 dp 陣列 函式的含義 明確 選擇 明確 base case f 0 0,f 1 1 f n f n 1 f n 2 其中 n 1.1 遞迴計算 複雜度高,指數級別 超時 時間複雜度 o 2 n cl...