序列DP leetcode 674 最长连续递增序列 原题链接:https://leetcode.cn/problems/longest-continuous-increasing-subsequence/description/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public int findLengthOfLCIS (int [] nums) { int n = nums.length; int [] f = new int [n]; Arrays.fill(f,1 ); int ans = 1 ; for (int i = 1 ; i < n ; i++){ if (nums[i] > nums[i -1 ] ){ f[i] = Math.max(f[i],f[i - 1 ] + 1 ); } ans = Math.max(ans,f[i]); } return ans; } }
leetcode 62 不同路径 原题链接:https://leetcode.cn/problems/unique-paths/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public int uniquePaths (int m, int n) { int [][] f = new int [m + 1 ][n + 1 ]; f[1 ][1 ] = 1 ; for (int i = 1 ; i <= m; i++){ for (int j = 1 ; j <= n ; j++){ f[i][j] += f[i - 1 ][j] + f[i][j - 1 ] ; } } return f[m][n]; } }
leetcode 70 爬楼梯 原题链接:https://leetcode.cn/problems/climbing-stairs/description/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public int climbStairs (int n) { if (n == 1 ){ return 1 ; } if (n == 2 ){ return 2 ; } int [] f = new int [n + 1 ]; f[1 ] = 1 ; f[2 ] = 2 ; for (int i = 3 ; i <= n ; i++){ f[i] = f[i - 1 ] + f[i - 2 ]; } return f[n]; } }
leetcode 64 最小路径和 原题链接:https://leetcode.cn/problems/minimum-path-sum/description/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { public int minPathSum (int [][] grid) { int m = grid.length; int n = grid[0 ].length; int [][] f = new int [m][n]; for (int i = 0 ; i < m; i++){ for (int j = 0 ; j < n ; j++){ if (i == 0 && j == 0 ){ f[i][j] = grid[i][j]; }else if (i == 0 ){ f[i][j] = f[i][j - 1 ] + grid[i][j]; }else if (j == 0 ){ f[i][j] = f[i - 1 ][j] + grid[i][j]; }else { f[i][j] = Math.min(f[i - 1 ][j],f[i][j - 1 ]) + grid[i][j]; } } } return f[m - 1 ][n - 1 ]; } }
leetcode 368 最大整除子集 原题链接:https://leetcode.cn/problems/largest-divisible-subset/description/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class Solution { public List<Integer> largestDivisibleSubset (int [] nums) { Arrays.sort(nums); int n = nums.length; int [] f = new int [n]; int [] g = new int [n]; for (int i = 0 ; i < n ; i++){ int prev = i; int len = 1 ; for (int j = 0 ; j < n ; j++){ if (nums[i] % nums[j] == 0 ){ if (len < f[j] + 1 ){ len = f[j] + 1 ; prev = j; } } } f[i] = len; g[i] = prev; } int idx = -1 ; int max = -1 ; for (int i = 0 ; i < n; i++){ if (f[i] > max){ max = f[i]; idx = i; } } List<Integer> ans = new ArrayList <>(); while (ans.size() < max){ ans.add(nums[idx]); idx = g[idx]; } return ans; } }
leetcode 300 最长递增子序列 原题链接:https://leetcode.cn/problems/longest-increasing-subsequence/description/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public int lengthOfLIS (int [] nums) { int n = nums.length; int [] f = new int [n + 1 ]; int ans = 1 ; for (int i = 0 ; i < n ; i++){ f[i] = 1 ; for (int j = 0 ; j < i ; j++){ if (nums[i] > nums[j]){ f[i] = Math.max(f[i], f[j] + 1 ); ans = Math.max(ans,f[i]); } } } return ans; } }
53 最大子数组和 原题链接:https://leetcode.cn/problems/maximum-subarray/?envType=daily-question&envId=2023-11-20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public int maxSubArray (int [] nums) { int n = nums.length; int [] f = new int [n]; f[0 ] = nums[0 ]; int ans = f[0 ]; for (int i = 1 ; i < n; i++){ f[i] = Math.max(nums[i],f[i - 1 ] + nums[i]); ans = Math.max(ans,f[i]); } return ans; } }
股票问题 leetcode 121. 买卖股票的最佳时机 这题可以用DP做 但不是最优解 最优解是枚举 只要有 后面的最大减前面最小的组合一组成立即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public int maxProfit (int [] prices) { int n = prices.length; int [][] f = new int [n][2 ]; f[0 ][0 ] = 0 ; f[0 ][1 ] = -prices[0 ]; for (int i = 1 ; i < n ; i++){ f[i][0 ] = Math.max(f[i - 1 ][0 ],f[i - 1 ][1 ] + prices[i]); f[i][1 ] = Math.max(f[i - 1 ][1 ],-prices[i]) ; } return Math.max(f[n - 1 ][0 ],f[n - 1 ][1 ]); } }
最优解 枚举
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public int maxProfit (int [] prices) { int min = Integer.MAX_VALUE; int n = prices.length; int ans = 0 ; for (int i = 0 ; i < n ;i++){ if (prices[i] < min){ min = prices[i]; } ans = Math.max(ans,prices[i] - min); } return ans; } }
leetcode 122. 买卖股票的最佳时机 II 原题链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/
用贪心做会更快一些 但dp也行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public int maxProfit (int [] prices) { int n = prices.length; int [][] f = new int [n][2 ]; f[0 ][0 ] = 0 ; f[0 ][1 ] = -prices[0 ]; for (int i = 1 ; i < n;i++){ f[i][0 ] = Math.max(f[i - 1 ][0 ],f[i - 1 ][1 ] + prices[i]); f[i][1 ] = Math.max(f[i - 1 ][1 ],f[i - 1 ][0 ] - prices[i]); } return Math.max(f[n - 1 ][0 ],f[n - 1 ][1 ]); } }
贪心解法
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public int maxProfit (int [] prices) { int res = 0 ; int n = prices.length; for (int i = 1 ; i < n ; i++){ res += Math.max(0 ,prices[i] - prices[i - 1 ]); } return res; } }
线性DP leetcode 97. 交错字符串 原题链接:https://leetcode.cn/problems/interleaving-string/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class Solution { char [] cs(String s){ return s.toCharArray(); } public boolean isInterleave (String s1, String s2, String s3) { int n = s1.length(), m = s2.length(); if (n + m != s3.length()){ return false ; } boolean [][] f = new boolean [n + 1 ][m + 1 ]; f[0 ][0 ] = true ; var cs1 = cs(s1); var cs2 = cs(s2); var cs3 = cs(s3); for (int i = 1 ; i <= n && f[i - 1 ][0 ] ; i++ ){ f[i][0 ] = cs1[i - 1 ] == cs3[i - 1 ]; } for (int i = 1 ; i <= m && f[0 ][i - 1 ]; i++){ f[0 ][i] = cs2[i - 1 ] == cs3[i - 1 ]; } for (int i = 1 ; i <= n ; i++){ for (int j = 1 ; j <= m ; j++ ){ if (cs1[i - 1 ] == cs3[i + j - 1 ]){ f[i][j] |= f[i - 1 ][j]; } if (cs2[j - 1 ] == cs3[i + j - 1 ]){ f[i][j] |= f[i][j - 1 ]; } } } return f[n][m]; } }
跳跃游戏 leetcode 55. 跳跃游戏 原题链接:https://leetcode.cn/problems/jump-game/
这题动态规划可以做 但不是最优解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Solution { public boolean canJump (int [] nums) { int n = nums.length; if (n <= 1 ){ return true ; } if (nums[0 ] == 0 ){ return false ; } int [] f = new int [n]; f[0 ] = nums[0 ]; for (int i = 1 ; i < n ; i++){ f[i] = Math.max(f[i - 1 ],nums[i] + i); if (f[i] >= n - 1 ){ return true ; } if (f[i] == i){ return false ; } } return true ; } }
一次遍历的解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution { public boolean canJump (int [] nums) { int n = nums.length; int k = 0 ; for (int i = 0 ; i < n ; i++){ if (i > k){ return false ; } k = Math.max(k,i + nums[i]); } return true ; } }
leetcode 45. 跳跃游戏 II 原题链接:https://leetcode.cn/problems/jump-game-ii/description/
DP可以做 但不是最优解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public int jump (int [] nums) { int n = nums.length; if (n <= 1 ){ return 0 ; } int [] f = new int [n]; Arrays.fill(f,Integer.MAX_VALUE); f[0 ] = 0 ; for (int i = 1 ; i < n; i++){ for (int j = 0 ; j < i ; j++){ if (nums[j] >= i - j){ f[i] = Math.min(f[j] + 1 ,f[i]); } } } return f[n - 1 ]; } }
最优解 贪心
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public int jump (int [] nums) { int n = nums.length; if (n <= 1 ){ return 0 ; } int next = 0 ; int end = 0 ; int ans = 0 ; for (int i = 0 ; i < n - 1 ; i++){ next = Math.max(next,i + nums[i]); if (end == i){ end = next; ans++; } } return ans; } }
树形DP acwing 285. 没有上司的舞会 原题链接:https://www.acwing.com/problem/content/287/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 import java.util.Arrays;import java.util.Scanner;public class Main { public static final int N = 6010 ; public static int [] e, h, ne, happy; public static boolean [] has_father; public static int [][] f; public static int idx; public static void main (String[] args) { e = new int [N]; ne = new int [N]; h = new int [N]; happy = new int [N]; has_father = new boolean [N]; Arrays.fill(h,-1 ); idx = 0 ; Scanner sc = new Scanner (System.in); int n = sc.nextInt(); for (int i = 1 ; i <= n ; i++){ happy[i] = sc.nextInt(); } for (int i = 0 ; i < n - 1 ; i++){ int a,b; a = sc.nextInt(); b = sc.nextInt(); has_father[a] = true ; add(b,a); } f = new int [N][2 ]; int root = 1 ; while (has_father[root]){ root++; } dfs(root); System.out.println(Math.max(f[root][0 ],f[root][1 ])); } public static void dfs (int u) { f[u][1 ] = happy[u]; for (int i = h[u]; i != -1 ; i = ne[i]){ int j = e[i]; dfs(j); f[u][0 ] += Math.max(f[j][0 ],f[j][1 ]); f[u][1 ] += f[j][0 ]; } } public static void add (int a,int b) { e[idx] = b; ne[idx] = h[a]; h[a] = idx++; } }