力扣刷题之动态规划
迪恩_Emma
喜欢看书的Java开发
展开
-
416. 分割等和子集(中等)
思路:0-1背包问题,就是选和不选的关系,动态规划dp代码:public class Solution { public boolean canPartition(int[] nums) { int n=nums.length; int sum=0; //先计算总和 for(int num:nums){ sum+=num; } //总和不能为奇数 if(sum%2==1){ return false;.原创 2021-06-13 11:09:39 · 54 阅读 · 0 评论 -
337. 打家劫舍 III(中等)
思路:动态规划dp,后序遍历(消除后效性)代码:class Solution { public int rob(TreeNode root) { //注意dfs返回的参数是int[],2个值(根节点偷/不偷),还要比较哪一种比较大 int[] res=dfs(root); return Math.max(res[0],res[1]); } private int[] dfs(TreeNode root){ if(root==null){ ret.原创 2021-06-12 11:02:21 · 55 阅读 · 0 评论 -
322. 零钱兑换(中等)
思路:跟287.寻找重复数方法一致,动态规划dp代码:class Solution { public int coinChange(int[] coins, int amount) { int n=coins.length; //要将长度设置为amount+1 int[] dp=new int[amount+1]; //用amount+1的初始化长度来创建dp //目的是判断是否没有数字符合 Arrays.fill(dp,amount+1); .原创 2021-06-12 10:34:13 · 59 阅读 · 0 评论 -
279. 完全平方数(中等)
思路:使用广度优先,设置一个队列、一个记录表代码:class Solution { public int numSquares(int n) { if(n==0||n==1) return n; //创建队列 Queue<Integer> queue=new LinkedList<>(); queue.offer(n); //visited boolean[] visited=new boolean[n]; i.原创 2021-04-08 10:03:08 · 121 阅读 · 1 评论 -
221. 最大正方形(中等)
思路:动态规划dp代码:class Solution { public int maximalSquare(char[][] matrix) { int max=0; if(matrix==null||matrix.length==0||matrix[0].length==0){ return max; } int m=matrix.length; int n=matrix[0].length; int[][] dp=new int[m][n].原创 2021-06-09 09:22:55 · 79 阅读 · 0 评论 -
200.打家劫舍(中等)
class Solution { public int rob(int[] nums) { int n=nums.length; if(n==0) return 0; if(n==1) return nums[0]; int[] dp=new int[n]; dp[0]=nums[0]; //注意不是dp[1]=nums[1],因为还有nums[0] dp[1]=Math.max(dp[0],nums[1]); for(int i=2;i<n;i..原创 2021-06-07 09:36:58 · 72 阅读 · 0 评论 -
152. 乘积最大子数组(中等)
思路:动态规划,但是此题不是使用dp,因为要记录2个数,min和max代码:class Solution { public int maxProduct(int[] nums) { //不能只使用dp,因为max和min都要记录 //imax和imin都初始化为1 int max=Integer.MIN_VALUE,imax=1,imin=1; for(int num:nums){ //当前数是负数时,调换最大和最小数 //因为负数*最小数就是最.原创 2021-06-07 09:13:15 · 91 阅读 · 0 评论 -
139. 单词拆分(中等)
思路:动态规划,哈希表代码:class Solution { public boolean wordBreak(String s, List<String> wordDict) { //直接放入set中,不用循环 Set<String> set=new HashSet<>(wordDict); boolean[] dp=new boolean[s.length()+1]; //一定要初始化 dp[0]=true; .原创 2021-06-05 10:38:42 · 58 阅读 · 0 评论 -
714. 买卖股票的最佳时机含手续费(中等)
思路:动态规划dp代码:class Solution { public int maxProfit(int[] prices, int fee) { int n=prices.length; int[][] dp=new int[n][2]; if(n<2) return 0; dp[0][0]=0; dp[0][1]=-prices[0]-fee; for(int i=1;i<n;i++){ //买入股票时就产生.原创 2021-06-04 09:40:42 · 74 阅读 · 0 评论 -
309. 最佳买卖股票时机含冷冻期(中等)
思路:动态规划dp代码:class Solution { public int maxProfit(int[] prices) { int n=prices.length; if(n<2) return 0; int[][] dp=new int[n][3]; //初始化 //0:不持股,不在冰冻期 //1:持股 //2:不持股,在冰冻期 dp[0][0]=0; dp[0][1]=-prices[0]; dp[0][2]=0;.原创 2021-06-04 09:35:52 · 82 阅读 · 0 评论 -
188. 买卖股票的最佳时机 IV(困难)
思路:与之前的股票问题不同的是,这里设置三维数组的dp,动态规划代码:class Solution { public int maxProfit(int k, int[] prices) { int n=prices.length; int[][][] dp=new int[n][k][2]; if(n<2||k==0) return 0; //n表示下标,k表示第几笔交易,2表示状态 //只有2种状态 //不持股(0) //持股(1) .原创 2021-06-04 09:25:21 · 53 阅读 · 0 评论 -
123. 买卖股票的最佳时机 III(困难)
思路:动态规划dp代码:class Solution { public int maxProfit(int[] prices) { int n=prices.length; if(n<2) return 0; //状态转移方程 //没有任何操作(0) //第一次买入(1) //第一次卖出(2) //第二次买入(3) //第二次卖出(4) int[][] dp=new int[n][5]; //初始化 dp[0][.原创 2021-06-03 10:29:40 · 73 阅读 · 0 评论 -
122. 买卖股票的最佳时机 II(简单)
思路:动态规划dp代码:class Solution { public int maxProfit(int[] prices) { int n=prices.length; int[][] dp=new int[n][2]; if(n<2) return 0; //状态转移方程 //不持股(0) //持股(1) //没有dp[0][2]从持股到不持股的状态是因为可以重复购买,所以没有限制 //初始化 dp[0][0.原创 2021-06-03 10:13:44 · 72 阅读 · 0 评论 -
121. 买卖股票的最佳时机(简单)
思路:动态规划dp代码:class Solution { public int maxProfit(int[] prices) { int n=prices.length; int[][] dp=new int[n][3]; if(n<2) return 0; //dp[i][0]:不持股,从来没有持股过。一直都是0 //dp[i][1]:第一次持股 //dp[i][2]:不持股,已卖出一次 //初始化 dp[0.原创 2021-06-03 10:05:41 · 104 阅读 · 0 评论 -
96. 不同的二叉搜索树(中等)
思路:动态规划假设n个节点存在二叉排序树的个数是G(n),令f(i)为以i为根的二叉搜索树的个数即有:G(n) = f(1) + f(2) + f(3) + f(4) + ... + f(n)n为根节点,当i为根节点时,其左子树节点个数为[1,2,3,...,i-1],右子树节点个数为[i+1,i+2,...n],所以当i为根节点时,其左子树节点个数为i-1个,右子树节点为n-i,即f(i) = G(i-1)*G(n-i)代码:class Solution { pu.原创 2021-06-02 09:32:48 · 64 阅读 · 0 评论 -
64. 最小路径和(中等)
思路:第一反应是用dfs递归回溯,但是最小值的剪枝不好做。此题实际上用动态规划dp代码:class Solution { public int minPathSum(int[][] grid) { int m=grid.length; int n=grid[0].length; int[][] dp=new int[m][n]; for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(i==0&.原创 2021-06-01 11:35:53 · 69 阅读 · 0 评论 -
63. 不同路径 II(中等)
思路:只有2个方向可以到达一个格,则使用dp,把前2种情况相加即可,不必使用递归dfs代码:class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m=obstacleGrid.length; int n=obstacleGrid[0].length; int[][] dp=new int[m][n]; //初始化第一行,但凡有一个障碍,后面的都走不到,.原创 2021-06-01 11:08:41 · 82 阅读 · 0 评论 -
62. 不同路径(中等)
思路:是动态规划的第一种代码:class Solution { public int uniquePaths(int m, int n) { int[][] dp=new int[m][n]; for(int i=0;i<m;i++){ dp[i][0]=1; } for(int i=0;i<n;i++){ dp[0][i]=1; } for(int i=1;i<m;i++){ for(int j=1;j&l.原创 2021-06-01 10:25:45 · 85 阅读 · 0 评论 -
5. 最长回文子串(中等)
思路:动态规划代码:class Solution { public String longestPalindrome(String s) { int len=s.length(); if(len<2){ return s; } boolean[][] dp=new boolean[len][len]; //初始化 for(int i=0;i<len;i++){ dp[i][i]=true; } int ma.原创 2021-05-22 10:45:17 · 151 阅读 · 0 评论 -
剑指 Offer 49. 丑数(中等)
思路:设置三个指针,每遍历到一个位置,都将该位置上三个指针的值分别乘以2、3、5,取最小值保存在该位置取到保存在该位置的指针可以+1代码:class Solution { public int nthUglyNumber(int n) { int a=0,b=0,c=0; int[] dp=new int[n]; dp[0]=1; for(int i=1;i<n;i++){ //注意是dp[a]*2而不是a*2 int n2=dp[a].原创 2021-05-08 09:40:32 · 102 阅读 · 0 评论 -
剑指 Offer 47. 礼物的最大价值(中等)
思路:动态规划dp代码:class Solution { public int maxValue(int[][] grid) { int m=grid.length; int n=grid[0].length; int[][] dp=new int[m+1][n+1]; //0行0列就算不初始化也是默认为0,所以从1开始就行 for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ dp[i][.原创 2021-05-07 10:33:15 · 76 阅读 · 0 评论 -
剑指 Offer 46. 把数字翻译成字符串(中等)
思路:一道经典的动态规划dp,判断前2个数是否满足>=10&&<=25,若满足,则有2种翻译方法,并且还要加上前面的所有情况方法一:dp方法二:用字母代替dp代码:方法一:class Solution { public int translateNum(int num) { String s=String.valueOf(num); //要比s的长度+1 int[] dp=new int[s.length()+1]; dp[.原创 2021-05-07 10:14:16 · 87 阅读 · 0 评论 -
剑指 Offer 42. 连续子数组的最大和(简单)
思路:动态规划dp代码:class Solution { public int maxSubArray(int[] nums) { int[] dp=new int[nums.length]; dp[0]=nums[0]; int max=dp[0]; for(int i=1;i<nums.length;i++){ dp[i]=Math.max(dp[i-1]+nums[i],nums[i]); max=Math.max(dp[i],max.原创 2021-05-05 15:18:26 · 52 阅读 · 0 评论 -
剑指 Offer 19. 正则表达式匹配(困难)
思路:有2种特殊字符:"*" 和 "." a*表示0或多个a,.表示可以是任何数代码:class Solution { public boolean isMatch(String s, String p) { int sLen=s.length(); int pLen=p.length(); //比s和p的长度多一行一列 boolean[][] dp=new boolean[sLen+1][pLen+1]; //是设为bool值而不是0/1 dp...原创 2021-04-23 10:30:28 · 92 阅读 · 0 评论 -
剑指 Offer 10- II. 青蛙跳台阶问题(简单)
思路:此题与剑指offer 10-I一样,都有三种方法:i)递归ii)非递归: 1)动态规划dp数组 2)动态规划优化的常量存值具体代码可看博文:(https://blog.csdn.net/di_ko/article/details/115818352)代码:方法二:class Solution { public int numWays(int n) { int[] dp=new int[n]; if(n<2) retur...原创 2021-04-18 10:12:29 · 128 阅读 · 0 评论 -
剑指 Offer 10- I. 斐波那契数列(简单)
思路:使用动态规划,设dp代码:class Solution { public int fib(int n) { int[] dp=new int[n+1]; if(n<2) return n; dp[0]=0; dp[1]=1; for(int i=2;i<=n;i++){ dp[i]=dp[i-1]+dp[i-2]; dp[i] %= 1000000007; } return dp.原创 2021-04-18 09:32:34 · 151 阅读 · 0 评论 -
354. 俄罗斯套娃信封问题(困难)
思路:方法一:动态规划 i)先将长度升序排列,遇到长度相同的,则降序排列,这样的目的是舍弃一个,只取一个,则把长度小的舍弃 ii)设置dp,经典双重循环,最后取dp中最大的,而不是最后一个方法二:贪心算法 i)同样要先排序 ii)若当前target比排好序的最后一个值大,则直接插入队尾 否则,使用二分查找,找到已排好序的队列中的大小刚好的位置,插入代码1(动态规划):class Solution { public...原创 2021-04-02 10:30:14 · 212 阅读 · 0 评论 -
343.整数拆分(中等)
思路:使用带有记忆化的动态规划dp代码:class Solution { public int integerBreak(int n) { int[] dp=new int[n+1]; //因为0和1都无法拆分,相乘为0,则从2开始,求部分最优解,一直到dp[n] for(int i=2;i<=n;i++){ int max=0; for(int j=1;j<i;j++){.原创 2021-04-01 09:53:14 · 68 阅读 · 0 评论 -
剑指 Offer 63. 股票的最大利润
思路:2种状态i)不持股(0)ii)持股(1)代码:class Solution { public int maxProfit(int[] prices) { int n=prices.length; if(n<2) return 0; int[][] dp=new int[n][3]; dp[0][0]=0;//不持股,无操作 dp[0][1]=-prices[0];//持股 dp[0][2]=Integer.MIN_VA.原创 2021-03-29 10:11:17 · 41 阅读 · 0 评论 -
188. 买卖股票的最佳时机 IV(困难)
思路:这里的限制是只能完成k笔交易则设置dp为三维数组,其中一维用来存储k(交易了几笔)分别表示:i)n表示下标ii)k代表笔数iii)2种状态代码:class Solution { public int maxProfit(int k, int[] prices) { int n=prices.length; int[][][] dp=new int[n][k][2]; if(n<2||k==0) return 0; //n表示下标,k原创 2021-03-29 09:28:30 · 71 阅读 · 0 评论 -
714. 买卖股票的最佳时机含手续费(中等)
思路:只有2种状态: i)不持股(0) ii)持股(1)这里dp定义为二维数组即可,不需要存储交易了几笔代码:class Solution { public int maxProfit(int[] prices, int fee) { int n=prices.length; int[][] dp=new int[n][2]; if(n<2) return 0; dp[0][0]=0; dp[0][1]=-prices...原创 2021-03-29 09:21:16 · 67 阅读 · 0 评论 -
123. 买卖股票的最佳时机 III(困难)
思路:与122不同的时,当前限制了只能交易2笔,则交易多少笔,就设多少种相应状态有5种状态: i)不持股,没有任何操作(0) ii)第一次买入(1) iii)第一次卖出(2) iiii)第二次买入(3) iiiii)第二次卖出(4)代码:class Solution { public int maxProfit(int[] prices) { int n=prices.length; if(n<2) return...原创 2021-03-28 11:32:37 · 62 阅读 · 0 评论 -
122. 买卖股票的最佳时机 II(简单)
思路:这次只有2种状态: i)不持股(0) ii)持股(1)不像121题,还要考虑是卖出的不持股还是本来就不持股。这道题因为有多次交易,就不用考虑一次都没有的不持股情况代码:class Solution { public int maxProfit(int[] prices) { int n=prices.length; int[][] dp=new int[n][2]; if(n<2) return 0; //状态转移方程 ...原创 2021-03-28 11:04:22 · 48 阅读 · 0 评论 -
121. 买卖股票的最佳时机(简单)
思路:分为三种情况: i)不持股,从来没有买进过(0) ii)持股,买进过一次(1) iii)不持股,卖掉了一次(2)设置dp[i][j],i表示下标为i,j表示状态(0~3)代码:class Solution { public int maxProfit(int[] prices) { int n=prices.length; int[][] dp=new int[n][3]; if(n<2) return 0; //dp[i][...原创 2021-03-28 10:51:00 · 52 阅读 · 0 评论 -
309. 最佳买卖股票时机含冷冻期(中等)
思路:分为三种情况:i)持股(dp[1])ii)不持股,不处在冰冻期(dp[0])iii)不持股,处在冰冻期(dp[2])代码:class Solution { public int maxProfit(int[] prices) { int n=prices.length; if(n<2) return 0; int[][] dp=new int[n][3]; //初始化 //0:不持股,不在冰冻期 //1:持股 //2:不持.原创 2021-03-28 10:07:25 · 72 阅读 · 0 评论 -
1143.最长公共子序列(中等)
思路:状态转移方程:使用双重遍历,如果text1的下标i的字符与text2的下标j的字符相同,则dp[i][j]=dp[i-1][j-1]+1在前一个值的基础上加1如果不相同,则取text1与text2中拥有公共子序列最多的情况dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1])代码:class Solution { public int longestCommonSubsequence(String text1, String tex.原创 2021-03-27 11:27:44 · 82 阅读 · 0 评论 -
53.最大子序和(简单)
思路:和最长递增子序列以及最长回文子序列类似,都是动态规划的经典例题状态转移方程:dp[i]表示当前数之前的的最大子序和1)若dp[i-1]为正数,直接加上nums[i]即可,dp[i]=dp[i-1]+nums[i]2)若dp[i-1]为负数,则dp[i]只取nums[i]一个数,相当于重新选新的子序最终dp[i]=Math.max(dp[i-1]+nums[i],nums[i])代码1:class Solution { public int maxSubA.原创 2021-03-27 10:24:34 · 88 阅读 · 0 评论 -
516.最长回文子序列(中等)
思路:从长度为2开始,每个长度从左到右遍历一遍,得到该长度是否满足(重叠子问题)长度加1,比较是否满足,若不满足,则取前一次长度的最优解(最优解问题)代码:class Solution { public int longestPalindromeSubseq(String s) { int n=s.length(); //这里的dp表示长度,不表示数值 int[][] dp=new int[n][n]; //将dp的对角线元素置为1,意思是单个元素.原创 2021-03-26 11:08:34 · 99 阅读 · 0 评论 -
300.最长递增子序列(中等)
思路:序列表示是可以不连续的,依赖于前面的解,要使用动态规划(dp)代码:class Solution { public int lengthOfLIS(int[] nums) { if(nums.length==0) return 0; int[] dp=new int[nums.length+1]; //把所有dp置为1,因为就算所有都不符合,到最后一个的时候自身也符合 Arrays.fill(dp,1); int res..原创 2021-03-26 09:58:16 · 72 阅读 · 0 评论 -
198.打家劫舍(中等)
思路:每次都隔一个,每次的结果都依赖前一次的结果,想到用动态规划满足条件:1)最优子问题:最后最优解是由每一个子最优解产生2)重叠子问题:计算当前解,得重复计算前面的代码:class Solution { public int rob(int[] nums) { int n=nums.length; if(n==0) return 0; if(n==1) return nums[0]; int[] dp=new int[n+1]; .原创 2021-03-26 09:32:24 · 54 阅读 · 0 评论