栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Leetcode刷题10-动态规划

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Leetcode刷题10-动态规划

动态规划 基础知识

动态规划是一种思想,因此这里主要讲解动态规划相关的习题及应用。

区间调度问题

1.无权区间调度问题

对于该问题,{b, e, h}是最大互相兼容的任务集合,这里需要使用贪心算法。

贪心算法:总是做出当前最优的选择,并不总能得到最优解,但是它是最简单最容易实现的算法。

无权区间调度问题贪心算法:先将任务以某种顺序排序,再按顺序挑选互相兼容的任务。

对于该问题,需要按照结束时间排序,时间复杂度是O(nlogn)

2.带权区间调度问题

动态规划四步骤:

确定状态:先按任务结束时间排序,定义状态OPT(j)为任务{1, 2, …, j}的最大权重,如

状态转移方程

初始条件和边界情况

确定计算顺序

在动态规划的实现中,可以使用自底向上(一般是for循环,易于理解)或者自顶向下(使用递归方式,可能可以节省一些不必要的计算)的方式实现。

补:在计算P(j)的时候,时间复杂度是O(n),需要将区间按照开始时间排序,和按照结束时间排序的结果,然后使用双指针计算P(j)即可。

背包问题

对于该题,按照贪心算法行不通,需要使用动态规划解决。

动态规划步骤:

注意其中左边的方式行不通,因为没有考虑背包的容量问题。

题目解析 最大子数组和

1.题目描述

题目链接

2.解析思路及代码

确定状态:OPT(i)表示以i结尾的连续子数组的最大和。

OPT(0) = nums[0]

OPT(i) = max(OPT(i - 1) + nums[i], nums[i])

	public int maxSubArray(int[] nums) {
        if (nums.length == 0)   return 0;
        int[] res = new int[nums.length];
        res[0] = nums[0];
        int ans = nums[0];
        for (int i = 1; i < nums.length; i ++ ) {
            res[i] = Math.max(res[i - 1] + nums[i], nums[i]);
            ans = Math.max(ans, res[i]);
        }
        return ans;
    }
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        res = []
        res.append(nums[0])
        for i in nums[1:]:
            res.append(max(res[-1] + i, i))
        return max(res)
最长公共子序列

1.题目描述

题目链接

2.解题思路及代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EIUsBlWO-1646490127700)(images/1007最长公共子序列状态转移方程.png)]

	public int longestCommonSubsequence(String text1, String text2) {
        int m = text1.length(), n = text2.length();
        
        int[][] dp = new int[m + 1][n + 1];
        
        for (int i = 1; i <= m; i ++ ) {
            char c1 = text1.charAt(i - 1);
            for (int j = 1; j <= n; j ++ ) {
                char c2 = text2.charAt(j - 1);
                
                if (c1 == c2) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        
        return dp[m][n];
    }
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        m, n = len(text1), len(text2)
        
        dp = [[0] * (n + 1) for _ in range(m + 1)]
        
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                if text1[i - 1] == text2[j - 1]:
                    dp[i][j] = dp[i - 1][j - 1] + 1
                else:
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
        
        return dp[m][n]
买卖股票的最佳时机

1.题目描述

题目链接

2.解题思路及代码

暴力解法O(n ^ 2)找到最低点,计算当前节点和最低点的差值即可。

	public int maxProfit(int[] prices) {
        int min = Integer.MAX_VALUE;
        int res = 0;
        for (int price : prices) {
            res = Math.max(res, price - min);
            min = Math.min(min, price);
        }
        return res;
    }
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        min_price = int(1e9)
        res = 0
        for price in prices:
            res = max(res, price - min_price)
            min_price = min(min_price, price)
        
        return res
买卖股票的最佳时机 II

1.题目描述

题目链接

2.解题思路及代码

贪心:ans += Math.max(0, prices[i] - princes[i - 1])动态规划: d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 1 ] + p r i c e s [ i ] ) d p [ i ] [ 1 ] = m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 0 ] − p r i c e s [ i ] ) 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][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])

	public int maxProfit(int[] prices) {
        int res = 0;
        
        for (int i = 1; i < prices.length; i ++ ) {
            res += Math.max(0, prices[i] - prices[i - 1]);
        }
        return res;
    }
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        res = 0
        for i in range(1, len(prices)):
            res += max(0, prices[i] - prices[i - 1])
            
        return res
最长回文子序列

1.题目描述

题目链接

2.解题思路及代码

插入排序的思路,需要注意两点:

防止边界问题,使用带有头结点的链表在找当前节点需要插入的位置时,正常针对数组的插入排序从i - 1开始找,但是这是链表,需要从头节点开始找。

	public int longestPalindromeSubseq(String s) {
        int n = s.length();
        int[][] dp = new int[n][n];
        for (int i = n - 1; i >= 0; i -- ) {
            dp[i][i] = 1;
            char c1 = s.charAt(i);
            for (int j = i + 1; j < n; j ++ ) {
                char c2 = s.charAt(j);
                if (c1 == c2) {
                    dp[i][j] = dp[i + 1][j - 1] + 2;
                } else {
                    dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
                }
            }
        }
        
        return dp[0][n - 1];
    }
class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        n = len(s)
        dp = [[0] * n for _ in range(n)]
        for i in range(n - 1, -1, -1):
            dp[i][i] = 1
            for j in range(i + 1, n):
                if s[i] == s[j]:
                    dp[i][j] = dp[i + 1][j - 1] + 2
                else:
                    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
        
        return dp[0][n - 1]
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/755454.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号