leetcode總結——動態規劃
動態規劃:
楊輝三角
最長迴文字串
最大乘積子陣列
01矩陣中最大的1正方形
機器人走路:
字元編碼
股票投資問題
三角路徑和:
打家劫舍
粉刷房子
平方陣列合
紙幣問題
樹形打家劫舍
楊輝三角:
給定一個非負索引 k,其中 k ≤ 33,返回楊輝三角的第 k 行。
在楊輝三角中,每個數是它左上方和右上方的數的和。
示例:
輸入: 3
輸出: [1,3,3,1]
解答一:
class Solution {
public List<Integer> getRow(int rowIndex) {
int max=33,row=1;
Integer[] k = new Integer[rowIndex + 1];
int num=0,num1=0,num2=0;//作為輔助空間
for(int i=0;i<=rowIndex;i++,row++){
for(int j=0;j<=i;j++){
if(j==0||j==i)
{
k[j]=1;
num2=1;
}
else
{
num1=k[j];
k[j]=num2+k[j];
num2=num1;
}
}
}
List<Integer> res = Arrays.asList(k);
return res;
}
}
注意:
1:類似於動態規劃問題 第i層的k[j] 等於第i-1層的k[j-1]+k[j]。所以如果只用一個陣列對其進行運算,需要儲存i-1層中j-1的值
num2為計算 第i層的k[j] 時儲存的 第i-1層的k[j-1] 的值【k[j]還未改變】
num1為儲存的第i層的k[j]的值,是為了方便之後的計算
2: Integer[] k = new Integer[rowIndex + 1] 轉化為 List res = Arrays.asList(k);
陣列轉化為連結串列的方法
public List<Integer> getRow(int rowIndex) {
Integer[] dp = new Integer[rowIndex + 1];
Arrays.fill(dp,1);
for(int i = 2;i < dp.length;i++){
for(int j = i - 1;j > 0;j--)
dp[j] = dp[j] + dp[j - 1];
}
List<Integer> res = Arrays.asList(dp);
return res;
}
注意:此為逆序運算,則不用儲存值
public List<Integer> getRow(int rowIndex) {
List<Integer> result = new ArrayList<>();
if (rowIndex == 0) {
result.add(1);
return result;
}
if (rowIndex == 1) {
result.add(1);
result.add(1);
return result;
}
result.add(1);
result.add(1);
for (int i = 1; i < rowIndex; i++) {
result.add(1);
for (int j = 0; j < i; j++) {
result.add(result.get(0) + result.get(1));
result.remove(0);
}
result.add(1);
result.remove(0);
}
return result;
}
注意:特殊的解法
最長迴文字串
題目四:
給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為 1000。
示例 1:
輸入: “babad”
輸出: “bab”
注意: “aba” 也是一個有效答案。
示例 2:
輸入: “cbbd”
輸出: “bb”
class Solution {
public String longestPalindrome(String s) {
int len=s.length();
if(len==0)return "";
int dp[][]=new int [len][len];
int maxlen=0;
String str=s.substring(0,1);//如果不存在長度>1的迴文子串,最長迴文串為1(首字元)
for(int i=1;i<len;i++){
for(int j=0;j<i;j++){
if((s.charAt(i)==s.charAt(j))&&((i-j)<=2||dp[j+1][i-1]==1)){
dp[j][i]=1;
if(i-j+1>=maxlen){
maxlen=i-j+1;
str=s.substring(j,i+1) ;
}
}
}
}
return str;
}
}
最大乘積子陣列
給定一個整數陣列 nums ,找出一個序列中乘積最大的連續子序列(該序列至少包含一個數)。
示例 1:
輸入: [2,3,-2,4]
輸出: 6
解釋: 子陣列 [2,3] 有最大乘積 6。
示例 2:
輸入: [-2,0,-1]
輸出: 0
解釋: 結果不能為 2, 因為 [-2,-1] 不是子陣列。
解析:類似於最大連續序列和的思想,只不過既要維護最小值也要維護最大值
import java.lang.*;
import java.util.*;
class Solution {
public int maxProduct(int[] nums) {
int len=nums.length;if(len==0)return 0;
int min[]=new int [len];
int max[]=new int [len];
min[0]=nums[0];
max[0]=nums[0];
int max1=nums[0];
for(int i=1;i<len;i++){
int num1=min[i-1]*nums[i];
int num2=max[i-1]*nums[i];
min[i]=Math.min(Math.min(num1,num2),nums[i]);
max[i]=Math.max(Math.max(num1,num2),nums[i]);
max1=Math.max(max1,max[i]);
}
return max1;
}
}
01矩陣中最大的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[i][j]=Math.min(Math.min(dp[i-1][j-1],dp[i-1][j]),dp[i][j-1])+1;
並且技巧是 new int [matrix.length+1][matrix[0].length+1];多了一維度矩陣,在判斷(1,n)(n,1)時不用單獨分析
class Solution {
public int maximalSquare(char[][] matrix) {
if(matrix.length==0)return 0;
int [][]dp=new int [matrix.length+1][matrix[0].length+1];
int max=0;
for(int i=1;i<=matrix.length;i++){
for(int j=1;j<=matrix[0].length;j++){
if(matrix[i-1][j-1]=='1'){
dp[i][j]=Math.min(Math.min(dp[i-1][j-1],dp[i-1][j]),dp[i][j-1])+1;
max=Math.max(max,dp[i][j]);
}
}
}
return max*max;
}
}
機器人走路:
一個機器人位於一個 m x n 網格的左上角 (起始點在下圖中標記為“Start” )。
機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為“Finish”)。
問總共有多少條不同的路徑?
輸入: m = 3, n = 2
輸出: 3
解釋:
從左上角開始,總共有 3 條路徑可以到達右下角。
- 向右 -> 向右 -> 向下
- 向右 -> 向下 -> 向右
- 向下 -> 向右 -> 向右
示例 2:
輸入: m = 7, n = 3
輸出: 28
解析:其實就是C(m-1)(m+n-2)的一個排列計算,但是因為會越界,所以當數字就沒有辦法實現
考慮動態規劃
class Solution {
public int uniquePaths(int m, int n) {
int [][]dp=new int [n+1][m+1];
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
dp[j][i]=Math.max(1,dp[j-1][i]+dp[j][i-1]);
}
}
return dp[n][m];
}
}
給定一個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。
說明:每次只能向下或者向右移動一步。
示例:
輸入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
輸出: 7
解釋: 因為路徑 1→3→1→1→1 的總和最小。
class Solution {
public int minPathSum(int[][] grid) {
int [][]dp=new int [grid.length][grid[0].length];
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[0].length;j++){
if(i0&j0)dp[i][j]=grid[i][j];
else if(i0)dp[i][j]=dp[i][j-1]+grid[i][j];
else if(j0)dp[i][j]=dp[i-1][j]+grid[i][j];
else dp[i][j]=Math.min(dp[i][j-1]+grid[i][j],dp[i-1][j]+grid[i][j]);
}
}
return dp[grid.length-1][grid[0].length-1];
}
}
字元編碼
一條包含字母 A-Z 的訊息通過以下方式進行了編碼:
‘A’ -> 1
‘B’ -> 2
…
‘Z’ -> 26
給定一個只包含數字的非空字串,請計算解碼方法的總數。
示例 1:
輸入: “12”
輸出: 2
解釋: 它可以解碼為 “AB”(1 2)或者 “L”(12)。
示例 2:
輸入: “226”
輸出: 3
解釋: 它可以解碼為 “BZ” (2 26), “VF” (22 6), 或者 “BBF” (2 2 6) 。
示例 3:
輸入:“01”
輸出:0
解釋:0無法解碼
public class test0511 {
public static void main(String[] args) {
Solution s = new Solution();
System.out.println(s.numDecodings(“101”));
}
}
class Solution {
public int numDecodings(String s) {
if(s.length() == 0 || s.charAt(0) ==‘0’ ){
return 0;
}
if(s.length() == 1 ){
return 1;
}
int dp1 = 1;//相當於dp[i-2]
int dp2 = 1;//相當於dp[i-1]
int result = 0;
for(int i = 1;i<s.length();i++){
int i1 = (s.charAt(i - 1) - 48) * 10 + (s.charAt(i) - 48);
//不能連續出現0
if(i1 == 0){
return 0;
}
if(i1 >=10 && i1 <=26 ){
result = dp1;
}
if(s.charAt(i) != ‘0’){
result += dp2;
}
dp1 = dp2;
dp2 = result;
result = 0;
}
return dp2;
}
}
三角路徑和:
給定一個三角形,找出自頂向下的最小路徑和。每一步只能移動到下一行中相鄰的結點上。
例如,給定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自頂向下的最小路徑和為 11(即,2 + 3 + 5 + 1 = 11)。
由底向上【妙啊!】
public int minimumTotal(List<List< Integer>> triangle) {
int row = triangle.size();
int[] minlen = new int[row+1];
for (int level = row-1;level>=0;level–){
for (int i = 0;i<=level;i++){ //第i行有i+1個數字
minlen[i] = Math.min(minlen[i], minlen[i+1]) + triangle.get(level).get(i);
}
}
return minlen[0];
}
股票投資問題:
這是要一個系列的動態規劃問題
dp[i][k][j]:其中i代表第幾天【0-N】,k代表可以買賣股票的次數[0-K],j代表當天是否持有股票[0,1] dp為最大的利潤
因為動態規劃肯定是轉移方程,所以我們有
dp[i][k][0]=max{dp[i-1][k][0],dp[i-1][k][1]+prices[i]}
dp[i][k][1]=max{dp[i-1][k][1],dp[i-1][k][0]-prices[i]}
再看看基礎情況
1:如果沒有買賣次數,肯定值為0:dp[i][0][j]=0
2:在第1天【I=0】的時候:
如果選擇購買股票,則,
dp[0][k][1]=-prices[i]
如果選擇不購買股票,則
dp[0][k][0]=0
接下來就解答題目:
題目一:k=1
dp[i][1][0]=max{dp[i-1][1][0],dp[i-1][0][1]+prices[i]}
dp[i][1][1]=max{dp[i-1][1][1],dp[i-1][1][0]-prices[i]}
因為dp[i-1][0][0]=0,又因為上述式中k全為1,可簡化為:
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
dp[i][1] = Math.max(dp[i-1][1], -prices[i]);
得到答案:
class Solution {
public int maxProfit(int[] prices) {
int [][]dp=new int [prices.length][2];
if(prices.length==0)return 0;
dp[0][0]=0;
dp[0][1]=-prices[0];
for(int i=1;i<prices.length;i++){
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
dp[i][1] = Math.max(dp[i-1][1], -prices[i]);
}
return dp[prices.length-1][0];
}
}
發現dp僅僅和相鄰的狀態有關,再簡化:
int maxProfit_k_1(int[] prices) {
int n = prices.length;
int dp_i_0 = 0, dp_i_1 =-prices[0];
for (int i = 1; i < n; i++) {
dp_i_0 = Math.max(dp_i_0, dp_i_1 + prices[i]);
dp_i_1 = Math.max(dp_i_1, -prices[i]);
}
return dp_i_0;
}
題目二:k=n
因為k為無限大,可以直接不考慮好難想到
得到方程:
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
又發現同樣也是,僅僅和相鄰狀態有關,再簡化:只不過這裡dp[i]兩個都和dp[i-1]有關,利用temp儲存其中一個值即可!!!!!
int temp = dp_i_0;
dp_i_0 = Math.max(dp_i_0, dp_i_1 + prices[i]);
dp_i_1 = Math.max(dp_i_1, temp - prices[i]);
int maxProfit_k_inf(int[] prices) {
int n = prices.length;
int dp_i_0 = 0, dp_i_1 =-prices[0];
for (int i = 1; i < n; i++) {
int temp = dp_i_0;
dp_i_0 = Math.max(dp_i_0, dp_i_1 + prices[i]);
dp_i_1 = Math.max(dp_i_1, temp - prices[i]);
}
return dp_i_0;
}
題目三:k=n且具有一天的冷凍期,即當天如果賣出股票,第二天無法買入
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-2][0] - prices[i])
原因在於dp[i-1][0]=max(dp[i-2][0], dp[i-2][1] + prices[i])又因為有冷凍期,所以不可能在I=i-2的時候賣出股票,所以dp[i-1][0]=dp[i-2][0]
class Solution {
public int maxProfit(int[] prices) {
int n = prices.length;
if(prices.length==0)return 0;
int dp_i_0 = 0, dp_i_1 =-prices[0];
int dp_pre_0 =0;
for (int i = 1; i < n; i++) {
int temp = dp_i_0;
dp_i_0 = Math.max(dp_i_0, dp_i_1 + prices[i]);
dp_i_1 = Math.max(dp_i_1, dp_pre_0 - prices[i]);
dp_pre_0 = temp;
}
return dp_i_0;
}
}
題目四:每一次賣出交手續費fee
dp_i_0 = Math.max(dp_i_0, dp_i_1 + prices[i]-fee);
dp_i_1 = Math.max(dp_i_1, temp - prices[i]);
}
class Solution {
int maxProfit(int[] prices, int fee) {
int n = prices.length;
int dp_i_0 = 0, dp_i_1 =-prices[0];
for (int i = 1; i < n; i++) {
int temp = dp_i_0;
dp_i_0 = Math.max(dp_i_0, dp_i_1 + prices[i]-fee);
dp_i_1 = Math.max(dp_i_1, temp - prices[i]);
}
return dp_i_0;
}
}
題目五:k=2
注意此時是一個三維陣列了,所以應該有兩個for迴圈
聯想三維矩陣
class Solution {
public int maxProfit(int[] prices) {
int max_k = 2;
int[][][] dp = new int[prices.length][max_k + 1][2];
if(prices.length==0)return 0;
for (int i=0;i <prices.length; i++) {
for (int k = max_k; k >= 1; k--) {
if (i - 1 == -1) {
/* 處理 base case */
dp[i][k][0] = 0;
dp[i][k][1] = -prices[i];
continue;
}
dp[i][k][0]=Math.max(dp[i-1][k][0], dp[i-1][k][1] + prices[i]);
dp[i][k][1]=Math.max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i]);
}
}
return dp[prices.length - 1][max_k][0];
}
}
或者:
class Solution {
public int maxProfit(int[] prices) {
int max_k = 2;
int[][][] dp = new int[prices.length][max_k + 1][2];
if(prices.length==0)return 0;
for (int k = 1; k <=max_k; k++) {
for (int i=0;i <prices.length; i++) {
if (i - 1 == -1) {
/* 處理 base case */
dp[i][k][0] = 0;
dp[i][k][1] = -prices[i];
continue;
}
dp[i][k][0]=Math.max(dp[i-1][k][0], dp[i-1][k][1] + prices[i]);
dp[i][k][1]=Math.max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i]);
}
}
return dp[prices.length - 1][max_k][0];
}
}
題目六:k任意次數
注意若k過大,我們設定的三維陣列也巨大,可能導致記憶體溢位。但是實際上最大的交換次數是n/2次,所以如果超過2/n,就轉換為問題題目二
class Solution {
public int maxProfit(int k, int[] prices) {
int n = prices.length;
if (k > n / 2)
return maxProfit(prices);//轉換為題目二
int[][][] dp = new int[n][k + 1][2];
for (int i = 0; i < n; i++)
for (int k = k; k >= 1; k--) {
if (i - 1 == -1) {
dp[i][k][0] = 0;
dp[i][k][1] = -prices[i];
continue;
}
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i]);
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i]);
}
return dp[n - 1][k][0];
}
}
打家劫舍:
你是一個專業的小偷,計劃偷竊沿街的房屋,每間房內都藏有一定的現金。這個地方所有的房屋都圍成一圈,這意味著第一個房屋和最後一個房屋是緊挨著的。同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
給定一個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。
示例 1:
輸入: [2,3,2]
輸出: 3
解釋: 你不能先偷竊 1 號房屋(金額 = 2),然後偷竊 3 號房屋(金額 = 2), 因為他們是相鄰的。
示例 2:
輸入: [1,2,3,1]
輸出: 4
解釋: 你可以先偷竊 1 號房屋(金額 = 1),然後偷竊 3 號房屋(金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。
環形陣列,將第一個和最後一個單獨討論
第一個偷:最後一個不偷
第一個不偷:最後一個偷
最後一個不偷
所以分為兩次動態規劃,第一次[1:]且第一次不偷:第二次[:n-1]且最後一次不偷
class Solution {
public int rob(int[] nums) {
if(nums.length == 0) return 0;
if(nums.length == 1) return nums[0];
return Math.max(myRob(Arrays.copyOfRange(nums, 0, nums.length - 1)),
myRob(Arrays.copyOfRange(nums, 1, nums.length)));
}
private int myRob(int[] nums) {
int a0=0, a1=0, tmp;
for(int i=0;i<nums.length;i++) {
tmp=a0;
a0=Math.max(a0,a1);
a1=tmp+nums[i];
}
return Math.max(a0,a1);
}
}
如果首尾不相鄰:
dp[i]=max(dp[i-1],dp[i-2]+nums[i])
原理同上
如果沒偷:dp[i]=dp[i-1]
如果偷了:dp[i]=dp[i-1]+nums[i] 又因為dp[i-1]=dp[i-2]
樹形打家劫舍
在上次打劫完一條街道之後和一圈房屋後,小偷又發現了一個新的可行竊的地區。這個地區只有一個入口,我們稱之為“根”。 除了“根”之外,每棟房子有且只有一個“父“房子與之相連。一番偵察之後,聰明的小偷意識到“這個地方的所有房屋的排列類似於一棵二叉樹”。 如果兩個直接相連的房子在同一天晚上被打劫,房屋將自動報警。
計算在不觸動警報的情況下,小偷一晚能夠盜取的最高金額。
示例 1:
輸入: [3,2,3,null,3,null,1]
3
/ \
2 3
\ \
3 1
輸出: 7
解釋: 小偷一晚能夠盜取的最高金額 = 3 + 3 + 1 = 7.
示例 2:
輸入: [3,4,5,1,3,null,1]
3
/ \
4 5
/ \ \
1 3 1
輸出: 9
解釋: 小偷一晚能夠盜取的最高金額 = 4 + 5 = 9.
public int rob(TreeNode root) {
if (root == null) return 0;
int money = root.val;
if (root.left != null) {
money += (rob(root.left.left) + rob(root.left.right));
}
if (root.right != null) {
money += (rob(root.right.left) + rob(root.right.right));
}
return Math.max(money, rob(root.left) + rob(root.right));
}
粉刷房子:
假如有一排房子,共 n 個,每個房子可以被粉刷成紅色、藍色或者綠色這三種顏色中的一種,你需要粉刷所有的房子並且使其相鄰的兩個房子顏色不能相同。
當然,因為市場上不同顏色油漆的價格不同,所以房子粉刷成不同顏色的花費成本也是不同的。每個房子粉刷成不同顏色的花費是以一個 n x 3 的矩陣來表示的。
例如,costs[0][0] 表示第 0 號房子粉刷成紅色的成本花費;costs[1][2] 表示第 1 號房子粉刷成綠色的花費,以此類推。請你計算出粉刷完所有房子最少的花費成本。
注意:
所有花費均為正整數。
示例:
輸入:
[[17,2,17],
[16,16,5],
[14,3,19]]
輸出: 10
解釋: 將 0 號房子粉刷成藍色,1 號房子粉刷成綠色,2 號房子粉刷成藍色。
最少花費: 2 + 5 + 3 = 10。
class Solution {
public int minCost(int[][] costs) {
if(costs.length==0)return 0;
int dp[]=new int [costs[0].length];
int tmp[]=new int [costs[0].length];
dp[0]=costs[0][0];
dp[1]=costs[0][1];
dp[2]=costs[0][2];
for(int i=0;i<costs.length;i++){
dp[0]=Math.min(tmp[1],tmp[2])+costs[i][0];
dp[1]=Math.min(tmp[0],tmp[2])+costs[i][1];
dp[2]=Math.min(tmp[0],tmp[1])+costs[i][2];
for(int j=0;j<costs[0].length;j++){
tmp[j]=dp[j];
}
}
return Math.min(Math.min(dp[0],dp[1]),dp[2]);
}
}
平方陣列合:
給定正整數 n,找到若干個完全平方數(比如 1, 4, 9, 16, …)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。
示例 1:
輸入: n = 12
輸出: 3
解釋: 12 = 4 + 4 + 4.
示例 2:
輸入: n = 13
輸出: 2
解釋: 13 = 4 + 9.
class Solution {
public int numSquares(int n) {
int[] dp = new int[n + 1]; // 預設初始化值都為0
for (int i = 1; i <= n; i++) {
dp[i] = i; // 最壞的情況就是每次+1
for (int j = 1; i - j * j >= 0; j++) {
dp[i] = Math.min(dp[i], dp[i - j * j] + 1); // 動態轉移方程
}
}
return dp[n];
}
}
紙幣問題
給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函式來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1。
示例 1:
輸入: coins = [1, 2, 5], amount = 11
輸出: 3
解釋: 11 = 5 + 5 + 1
示例 2:
輸入: coins = [2], amount = 3
輸出: -1
說明:
你可以認為每種硬幣的數量是無限的。
public class Solution {
public int coinChange(int[] coins, int amount) {
int max = amount + 1;
int[] dp = new int[amount + 1];
Arrays.fill(dp, max);
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coins.length; j++) {
if (coins[j] <= i) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
}
相關文章
- LeetCode動態規劃總結LeetCode動態規劃
- leetcode-動態規劃總結LeetCode動態規劃
- [LeetCode] 動態規劃題型總結LeetCode動態規劃
- 動態規劃 總結動態規劃
- LeetCode總結,動態規劃問題小結LeetCode動態規劃
- [leetcode初級演算法]動態規劃總結LeetCode演算法動態規劃
- 一維動態規劃總結動態規劃
- [leetcode] 動態規劃(Ⅰ)LeetCode動態規劃
- 總結 | 動態規劃十問十答動態規劃
- 動態規劃分類題目總結動態規劃
- 演算法之動態規劃總結演算法動態規劃
- 【DP專輯】ACM動態規劃總結ACM動態規劃
- leetcode:動態規劃( hard )LeetCode動態規劃
- 動態規劃小結動態規劃
- leetcode題解(動態規劃)LeetCode動態規劃
- 【LeetCode】Word Break 動態規劃LeetCode動態規劃
- 德魯週記10--15天從0開始刷動態規劃(leetcode動態規劃題目型別總結)動態規劃LeetCode型別
- 【leetcode】741 摘櫻桃(動態規劃)LeetCode動態規劃
- 【LeetCode】Word Break II 動態規劃LeetCode動態規劃
- 【動態規劃(一)】動態規劃基礎動態規劃
- Leetcode 編輯距離(動態規劃)LeetCode動態規劃
- LeetCode 動態規劃 House Robber 習題LeetCode動態規劃
- [leetcode 1235] [動態規劃]LeetCode動態規劃
- 動態規劃動態規劃
- LeetCode 分割回文串II(動態規劃)LeetCode動態規劃
- LeetCode入門指南 之 動態規劃思想LeetCode動態規劃
- LeetCode:動態規劃+貪心題目整理LeetCode動態規劃
- LeetCode 343. 整數拆分--動態規劃LeetCode動態規劃
- 【LeetCode】55. 跳躍遊戲 (動態規劃)LeetCode遊戲動態規劃
- 動態規劃入門——動態規劃與資料結構的結合,在樹上做DP動態規劃資料結構
- 動態規劃此一篇就夠了 萬字總結!動態規劃
- 圖解Leetcode組合總和系列——回溯(剪枝優化)+動態規劃圖解LeetCode優化動態規劃
- 動態規劃分析動態規劃
- 動態規劃(DP)動態規劃
- 動態規劃初步動態規劃
- 模板 - 動態規劃動態規劃
- 動態規劃法動態規劃
- Leetcode 題解演算法之動態規劃LeetCode演算法動態規劃