【日常系列】LeetCode《28·动态规划3》

news2024/9/28 16:54:17

数据规模->时间复杂度

<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(logn),o(1)

内容

二维数组中的路径问题
买卖股票的最佳时机

lc 62【剑指 098】【top100】:不同路径
https://leetcode.cn/problems/unique-paths/
提示:
1 <= m, n <= 100
题目数据保证答案小于等于 2 * 10^9
在这里插入图片描述
在这里插入图片描述

#方案一:dfs+记忆化
class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        memo=[[-1]*n for _ in range(m)]
        def dfs(i,j):
            if i==m-1 and j==n-1:return 1
            if i>=m or j>=n:return 0
            if memo[i][j]!=-1:return memo[i][j]
            #
            memo[i][j]=dfs(i+1,j)+dfs(i,j+1)
            return memo[i][j] #后序
        return dfs(0,0)

#方案二:dp(自底而上,左上至右下路径数更新)+压缩
class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        dp=[[0]*n for _ in range(m)] #[i][j]到[m-1][n-1]的路径数
        for i in range(m-1,-1,-1):
            for j in range(n-1,-1,-1):
                if i==m-1 or j==n-1:dp[i][j]=1 #最后一行/一列
                else:dp[i][j]=dp[i+1][j]+dp[i][j+1]
        return dp[0][0]

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        dp=[0]*n 
        for i in range(m-1,-1,-1):
            for j in range(n-1,-1,-1):
                if j==n-1:dp[j]=1 #最后一行/一列
                else:dp[j]=dp[j]+dp[j+1]
        return dp[0]
        
#方案三:dp(自上而下,右下至左上路径数更新)

lc 63 :不同路径 II
https://leetcode.cn/problems/unique-paths-ii/
提示:
m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j] 为 0 或 1
在这里插入图片描述

#方案一:dp
class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        m,n=len(obstacleGrid),len(obstacleGrid[0])
        dp=[[0]*n for _ in range(m)]
        #
        if obstacleGrid[0][0]==0:dp[0][0]=1
        for i in range(m):
            if dp[i-1][0]==1 and obstacleGrid[i][0]==0:dp[i][0]=1    
        for j in range(n):
            if dp[0][j-1]==1 and obstacleGrid[0][j]==0:dp[0][j]=1
        #
        for i in range(1,m):#key:1
            for j in range(1,n):
                if obstacleGrid[i][j]==1:continue
                dp[i][j]=dp[i-1][j]+dp[i][j-1]
        #
        return dp[m-1][n-1]
class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        m,n=len(obstacleGrid),len(obstacleGrid[0])
        dp=[[0]*n for _ in range(m)]
        #
        for i in range(m):#key:1
            for j in range(n):
                if obstacleGrid[i][j]==1:continue
                
                if i==0 and j==0:dp[i][j]=1
                elif j==0:#此时obstacleGrid[i][j]==0
                    dp[i][j]=dp[i-1][j]
                elif i==0:
                    dp[i][j]=dp[i][j-1]
                else:
                    dp[i][j]=dp[i-1][j]+dp[i][j-1]
        #
        return dp[m-1][n-1]
      

lc 120【剑指 100】:三角形最小路径和
https://leetcode.cn/problems/triangle/
提示:
1 <= triangle.length <= 200
triangle[0].length == 1
triangle[i].length == triangle[i - 1].length + 1
-10^4 <= triangle[i][j] <= 10^4
进阶:
你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题吗?
在这里插入图片描述
在这里插入图片描述

#方案一:dfs
class Solution:
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        m=len(triangle) #注意:len(triangle[0])=1
        memo=[[float('inf')]*m for _ in range(m)]
        #
        def dfs(i,j):
            if i==m or j==m:return 0
            if memo[i][j]!=float('inf'):return memo[i][j]
            #
            memo[i][j]=min(dfs(i+1,j),dfs(i+1,j+1))+triangle[i][j]
            return memo[i][j]
        return dfs(0,0)
#方案二:dp
class Solution:
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        m=len(triangle) #注意:len(triangle[0])=1
        dp=[[float('inf')]*m for _ in range(m)]
        #
        for j in range(m):
            dp[m-1][j]=triangle[m-1][j]
        
        for i in range(m-2,-1,-1):
            for j in range(i+1):
                dp[i][j]=min(dp[i+1][j],dp[i+1][j+1])+triangle[i][j]
      
        return dp[0][0]
        
#方案三:dp+压缩
class Solution:
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        m=len(triangle) #注意:len(triangle[0])=1
        dp=[float('inf')]*m 
        #
        for j in range(m):
            dp[j]=triangle[m-1][j]
        
        for i in range(m-2,-1,-1):
            for j in range(i+1):
                dp[j]=min(dp[j],dp[j+1])+triangle[i][j]
      
        return dp[0]

lc 97【剑指 096】:交错字符串
https://leetcode.cn/problems/interleaving-string/
注意:a + b 意味着字符串 a 和 b 连接。
提示:
0 <= s1.length, s2.length <= 100
0 <= s3.length <= 200
s1、s2、和 s3 都由小写英文字母组成
进阶:
您能否仅使用 O(s2.length) 额外的内存空间来解决它?
在这里插入图片描述

#dp
class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        m,n,t=len(s1),len(s2),len(s3)
        if m+n != t:return False
        dp=[[False]*(n+1) for _ in range(m+1)]
        dp[0][0]=True
        #
        for i in range(1,m+1):
            if s1[i-1]==s3[i-1]:
                dp[i][0]=True #注意dp的i对应字符位置i-1
            else:break
        for j in range(1,n+1):
            if s2[j-1]==s3[j-1]:
                dp[0][j]=True
            else:break
        #
        for i in range(1,m+1):
            for j in range(1,n+1):
                k=i+j
                s1_s3=s1[i-1]==s3[k-1] and dp[i-1][j]#s1第i个字符、前i-1字符的匹配情况
                s2_s3=s2[j-1]==s3[k-1] and dp[i][j-1]
                dp[i][j]=s1_s3 or s2_s3 #考虑两种方向
        #
        return dp[m][n]

lc 221【top100】: 最大正方形
https://leetcode.cn/problems/maximal-square/
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 300
matrix[i][j] 为 ‘0’ 或 ‘1’
在这里插入图片描述

class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        m,n=len(matrix),len(matrix[0])
        #
        dp=[[0]*(n+1) for _ in range(m+1)]#key:有利于统一化

        max_len=0
        # for i in range(m):
        #     if matrix[i][0]=='1':
        #         dp[i][0]=1
        #         max_len=max(max_len,dp[i][0])
        # for j in range(n):
        #     if matrix[0][j]=='1':
        #         dp[0][j]=1
        #         max_len=max(max_len,dp[0][j])

        for i in range(1,m+1):
            for j in range(1,n+1):
                if matrix[i-1][j-1]=='1':
                    dp[i][j]=min(dp[i-1][j-1],min(dp[i][j-1],dp[i-1][j]))+1 #key
                    max_len=max(max_len,dp[i][j])
        return max_len**2     

系列算法题:买卖股票的最佳时机
在这里插入图片描述
在这里插入图片描述

lc 121【剑指 63】【top100】:买卖股票的最佳时机
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/
提示:
1 <= prices.length <= 10^5
0 <= prices[i] <= 10^4

# k=1->省去一维[k]
#方案一:dp
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        m=len(prices)
        
        dp=[[0]*2 for _ in range(m)]
        dp[0][0],dp[0][1]=0,-prices[0]

        for i in range(1,m):
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i])
            dp[i][1]=max(dp[i-1][1],0-prices[i])
        
        return dp[m-1][0]
#方案二:dp+压缩
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        m=len(prices)
        
        dp=[0]*2 #或者用两个变量
        dp[0],dp[1]=0,-prices[0]

        for i in range(1,m):
            dp[0]=max(dp[0],dp[1]+prices[i])
            dp[1]=max(dp[1],0-prices[i])
        
        return dp[0]        

lc 122 :买卖股票的最佳时机 II
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/
提示:
1 <= prices.length <= 3 * 10^4
0 <= prices[i] <= 10^4

#k=无穷,k-1=无穷->省去一维[k]
#dp
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        m=len(prices)
        
        dp=[[0]*2 for _ in range(m)]
        dp[0][0],dp[0][1]=0,-prices[0]

        for i in range(1,m):
            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])#key
        
        return dp[m-1][0]
#dp+压缩 
##也可以变成两个变量        

lc 123 :买卖股票的最佳时机 III
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
提示:
1 <= prices.length <= 10^5
0 <= prices[i] <= 10^5

#<=2:2,1((从 1 开始),第 0 次交易的话,利润肯定是0)
#dp
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n=len(prices)
        
        dp=[[[0]*2 for _ in range(3)] for _ in range(n)]
        dp[0][1][0]=dp[0][2][0]=0
        dp[0][1][1]=dp[0][2][1]=-prices[0]

        for i in range(1,n):
            dp[i][1][0]=max(dp[i-1][1][0],dp[i-1][1][1]+prices[i])
            dp[i][1][1]=max(dp[i-1][1][1],dp[i-1][0][0]-prices[i])
            dp[i][2][0]=max(dp[i-1][2][0],dp[i-1][2][1]+prices[i])
            dp[i][2][1]=max(dp[i-1][2][1],dp[i-1][1][0]-prices[i])

        return dp[n-1][2][0]
#dp+压缩
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n=len(prices)
        
        dp=[[0]*2 for _ in range(3)]
        dp[1][0]=dp[2][0]=0 #也可以变成四个变量
        dp[1][1]=dp[2][1]=-prices[0]

        for i in range(1,n):
            dp[1][0]=max(dp[1][0],dp[1][1]+prices[i])
            dp[1][1]=max(dp[1][1],dp[0][0]-prices[i])
            dp[2][0]=max(dp[2][0],dp[2][1]+prices[i])
            dp[2][1]=max(dp[2][1],dp[1][0]-prices[i])

        return dp[2][0]        

lc 188 :买卖股票的最佳时机 IV
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/
注意:
你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
提示:
0 <= k <= 100
0 <= prices.length <= 1000
0 <= prices[i] <= 1000

#方案一:dp
##<=k:k,k-1,...,1((从 1 开始),第 0 次交易的话,利润肯定是0)
class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        n=len(prices)
        
        dp=[[[0]*2 for _ in range(k+1)] for _ in range(n)]

        for j in range(1,k+1):
            dp[0][j][0]=0
            dp[0][j][1]=-prices[0]
        
        for i in range(1,n):
            for j in range(1,k+1):
                dp[i][j][0]=max(dp[i-1][j][0], dp[i-1][j][1]+prices[i])
                dp[i][j][1]=max(dp[i-1][j][1], dp[i-1][j-1][0]-prices[i])

        return dp[n-1][k][0]
#方案二:dp+优化(贪心)
class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        n=len(prices)

        #这里相当于'无限取'->贪心
        if k>=n//2:
            res=0
            for i in range(1,n):
                if prices[i]>prices[i-1]:
                    res+=prices[i]-prices[i-1]
            return res 
   
        dp=[[[0]*2 for _ in range(k+1)] for _ in range(n)]

        for j in range(1,k+1):
            dp[0][j][0]=0
            dp[0][j][1]=-prices[0]
        
        for i in range(1,n):
            for j in range(1,k+1):
                dp[i][j][0]=max(dp[i-1][j][0], dp[i-1][j][1]+prices[i])
                dp[i][j][1]=max(dp[i-1][j][1], dp[i-1][j-1][0]-prices[i])

        return dp[n-1][k][0]
#方案三:dp+压缩
##去除一维

lc 309【top100】:最佳买卖股票时机含冷冻期
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/
注意:
你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
提示:
1 <= prices.length <= 5000
0 <= prices[i] <= 1000

#dp
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n=len(prices)
        #
        dp=[[0]*2 for _ in range(n)]
        dp[0][0]=0
        dp[0][1]=-prices[0]
        #
        for i in range(1,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])#i-1天卖出股票后,无法在i天买入股票 (即冷冻期为 1 天)->i-2天卖
        return dp[n-1][0]
#dp+压缩
##去除一维

lc 714 :买卖股票的最佳时机含手续费
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/
注意:
这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。
提示:
1 <= prices.length <= 5 * 10^4
1 <= prices[i] < 5 * 10^4
0 <= fee < 5 * 10^4

#dp
class Solution:
    def maxProfit(self, prices: List[int], fee: int) -> int:
        n=len(prices)
        #
        dp=[[0]*2 for _ in range(n)]
        dp[0][0]=0
        dp[0][1]=-prices[0]-fee#你每笔交易都需要付手续费(这里统一用在买入时)
        #
        for i in range(1,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-1][0]-prices[i]-fee)
        return dp[n-1][0]
#dp+压缩
#去除一维/用两个量代替    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/174646.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分享优秀的视频地址

【2022 RISC-V中国峰会-芯来演讲合集】https://www.bilibili.com/video/BV1mV4y1W785?vd_source733efcf14020a43e7dac58e4c28ca0c8【计算机组成与设计&#xff1a;RISC-V【浙江大学】】https://www.bilibili.com/video/BV1tz411z7GN?vd_source733efcf14020a43e7dac58e4c28ca0…

【Dat图片的位异或解密】

文章目录 异或一、图片字节标识二、开始异或计算异或 异或(eor)是一个数学运算符。它应用于逻辑运算。异或的数学符号为"⊕"&#xff0c;计算机符号为"eor"。其运算法则为: a⊕b (a ∧ b) ∨ (a ∧b) 如果a、b两个值不相同&#xff0c;则异或结果为1。…

Tkinter的Label与Button

Tkinter是Python的一个内置包&#xff0c;主要用于简单的界面设计&#xff0c;使用起来非常方便。 目录 一、创建界面 1. 具体步骤 1.1 导入tkinter包 1.2 tk.Tk()函数&#xff1a;创建一个主界面&#xff0c;并命名为root 1.3 root.title()函数&#xff1a;给root界面设置…

API 接口案例--基于 MySQL 数据库 + Express对外提供用户列表的 API 接口服务

API 接口案例1. 案例需求2. 主要的实现步骤3. 搭建项目的基本结构4. 创建基本的服务器5. 创建 db 数据库操作模块6. 创建 user_ctrl 模块7. 创建 user_router 模块8. 导入并挂载路由模块9. 使用 try…catch 捕获异常1. 案例需求 基于 MySQL 数据库 Express 对外提供用户列表的…

【论文速递】WACV2022 - 基于小样本分割的多尺度Non-Novel片段消除方法

【论文速递】WACV2022 - 基于小样本分割的多尺度Non-Novel片段消除方法 【论文原文】&#xff1a;Elimination of Non-Novel Segments at Multi-Scale for Few-Shot Segmentation 获取地址&#xff1a;https://openaccess.thecvf.com/content/WACV2023/papers/Kayabasi_Elimi…

【睿睿的2022年度总结和2023的目标】

博客主页&#xff1a;张栩睿的博客主页欢迎关注&#xff1a;点赞收藏留言系列专栏&#xff1a;c语言学习家人们写博客真的很花时间的&#xff0c;你们的点赞和关注对我真的很重要&#xff0c;希望各位路过的朋友们能多多点赞并关注我&#xff0c;我会随时互关的&#xff0c;欢迎…

畅捷通T+与道一云对接集成报销凭证

畅捷通T与道一云对接集成获取报销信息列表连通凭证创建(报销保险费&#xff08;甘肃&#xff09;)数据源系统:道一云在道一云坚实的技术基础上&#xff0c;道一云推出全新升级的2.0产品矩阵&#xff0c;分别是低码平台、智能门户、场景应用。基于云原生底座&#xff0c;为企业提…

Allegro如何设置等长规则操作指导

Allegro如何设置等长规则操作指导 PCB设计需要给某一组信号做组间等长的时候,需要给这个组设置等长规则,如下图 以给以下两个网络设置等长规则为例 具体操作如下 打开规则管理器

【华为上机真题 2023】寻找相同子串

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…

(17)go-micro微服务Prometheus监控

文章目录一 Prometheus监控介绍1.微服务监控系统promethues介绍2.微服务监控系统promethues工作流程二 Prometheus监控重要组件和重要概念1.微服务监控系统promethues重要组件2.微服务监控系统promethues重要概念三 微服务监控系统grafana看板四 Prometheus监控Grafana看板安装…

【LeetCode每日一题:1817. 查找用户活跃分钟数~~~读懂题目意思+HashMap】

题目描述 给你用户在 LeetCode 的操作日志&#xff0c;和一个整数 k 。日志用一个二维整数数组 logs 表示&#xff0c;其中每个 logs[i] [IDi, timei] 表示 ID 为 IDi 的用户在 timei 分钟时执行了某个操作。 多个用户 可以同时执行操作&#xff0c;单个用户可以在同一分钟内…

数据库 | 事务相关知识点总结

本专栏收录了数据库的知识点&#xff0c;而从本文起&#xff0c;将讲述有关于数据库设计有关知识点&#xff0c;提供给有需要的小伙伴进行学习&#xff0c;本专栏地址可以戳下面链接查看 &#x1f388; 数据库知识点总结&#xff08;持续更新中&#xff09;&#xff1a;【数据库…

LeetCode101_101. 对称二叉树

LeetCode101_101. 对称二叉树 一、描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1…

多表查询与7种JOINS的实现

文章目录1.案例多表连接案例说明笛卡尔积&#xff08;或交叉连接&#xff09;2. 多表查询分类讲解角度1&#xff1a;等值连接与非等值连接角度2&#xff1a;自连接与非自连接角度3&#xff1a;内连接与外连接SQL92&#xff1a;使用()创建连接3. SQL99语法实现多表查询内连接(IN…

分类回归树简单理解总结

CART 决策树 CART决策树&#xff08;Classification And Regression Tree&#xff09;&#xff0c;可以做为分类树也可以作为回归树。 什么是回归树&#xff1f; 在分类树中我们可以处理离散的数据&#xff08;数据种类有限的数据&#xff09;它输出的数据样本是数据的类别&…

E. Arithmetic Operations 根号分治

题意&#xff1a;1e5长的数组&#xff0c;ai<1e5&#xff0c;问要将其变成等差数列的最小次数&#xff1b; 分析&#xff1a; 简单分析可得 —— 显然这个答案是固定的&#xff0c;就是原数列本来就能成为等差数列的最大个数。 但是最直接的想法是 的&#xff0c;一维枚举…

java继承2023022

继承 Java的继承具有单继承的特点&#xff0c;每个子类只有一个直接父类。但是可以有无限多个间接父类注意一点&#xff1a;子类能继承过来啥&#xff1f;子类只能从被扩展的父类获得成员变量、方法和内部类&#xff08;包括内部接口、枚举&#xff09;&#xff0c;不能获得构造…

Linux网络编程套接字

文章目录一、预备知识1. IP 地址2.端口号3. TCP 协议和 UDP 协议4.网络字节序二、socket 编程接口0. socket 常见 API1. socket 系统调用2. bind 系统调用3. recvfrom 系统调用4. sendto 系统调用5. listen 系统调用6. accept 系统调用7. connect 系统调用三、简单的 UDP 网络程…

Cert Manager 申请SSL证书流程及相关概念-二

中英文对照表 英文英文 - K8S CRD中文备注certificatesCertificate证书certificates.cert-manager.io/v1certificate issuersIssuer证书颁发者issuers.cert-manager.ioClusterIssuer集群证书颁发者clusterissuers.cert-manager.iocertificate requestCertificateRequest证书申…

用栈实现队列

题目&#xff1a;232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09;这题跟我们之前写过的 用队列实现栈 很像&#xff0c;感兴趣的可以自行了解一下。题目内容准备工作这题明确说明了需要用栈来实现队列&#xff0c;介于C语言没有队列的库&#xff0c;所以在此之前我们…