【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总(2)

简介: 【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总

【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总(1)https://developer.aliyun.com/article/1536617

经典题目  

*最长回文子串  

         

# 动态规划
# 用 P(i,j)P(i,j) 表示字符串 s的第 i 到 j 个字母组成的串(下文表示成 s[i:j])是否为回文串
class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        dp = [[False] * n for _ in range(n)]
        ans = ""
        # 枚举子串的长度 l+1
        for l in range(n):
            # 枚举子串的起始位置 i,这样可以通过 j=i+l 得到子串的结束位置
            for i in range(n-l):
                j = i + l
                if l == 0:
                    dp[i][j] = True        
                elif l == 1:
                    dp[i][j] = (s[i] == s[j])
                else:
                    dp[i][j] = (dp[i + 1][j - 1] and s[i] == s[j])
                if dp[i][j] and l + 1 > len(ans):
                    ans = s[i:j+1]
        return ans
                  
                  
# 中心扩展法
class Solution:
    def expandAroundCenter(self, s, left, right):
        while left >= 0 and right < len(s) and s[left] == s[right]:
            left -= 1
            right += 1
        return left + 1, right - 1
                  
    def longestPalindrome(self, s: str) -> str:
        # 中心扩展法,每个字符从中心往两边扩展,分奇偶
        start, end = 0, 0
        for i in range(len(s)):
            left1, right1 = self.expandAroundCenter(s, i, i) # 以当前字符为中心
            left2, right2 = self.expandAroundCenter(s, i, i + 1) # 以当前字符与后面一个字符为中心
            if right1 - left1 > end - start:
                start, end = left1, right1
            if right2 - left2 > end - start:
                start, end = left2, right2
        return s[start: end + 1]

             

*最长有效括号  

法一:动态规划

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        # 动态规划
        # dp[i] 表示以i结尾的最长有效括号长度,‘(’对应的一定是0
        n = len(s)
        if n == 0:
            return 0
        dp = [0] * n
        for i in range(1,n):
            # i- dp[i-1] -1是与当前')'对称的位置
            # dp[i-dp[i-1]-2] 表示与当前')'对称的位置前面的有效括号长度,需加上
            if s[i]==')' and i - dp[i-1] - 1>=0 and s[i - dp[i-1] - 1] == '(':
                dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2
        return max(dp)

         

法二:栈

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        # 栈来实现
        stack = [-1]
        length = 0
        max_length = 0        
        for i in range(len(s)):
            if s[i] == '(':
                stack.append(i)
            else:
                stack.pop()
                if not stack:
                # 栈为空,则添加当前右括号的索引入栈,为分割标识
                    stack.append(i)
                else:
                    length = i - stack[-1]
                    max_length = max(max_length, length)
        return max_length

         

*不同的子序列  

             

class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        # S中T出现的个数
        # dp[i][j]表示t的前i个字符串可以由s的前j个字符串组成多少个
        n = len(s) # 列
        m = len(t) # 行
        dp = [[0] * (n+1) for _ in range(m+1)]
        for j in range(n+1):
            dp[0][j] = 1
        for i in range(1,m + 1):
            for j in range(1, n + 1):
                if t[i-1] == s[j-1]:
# 对应于两种情况,s选择当前字母和不选择当前字母
# s选择当前字母dp[i-1][j-1]
# s不选择当前字母 dp[i][j-1]
                    dp[i][j] = dp[i-1][j-1] + dp[i][j-1]
                else:
                    dp[i][j] = dp[i][j-1]
        return dp[-1][-1]

             

         

*最长公共子序列  

参考:https://leetcode-cn.com/problems/longest-common-subsequence/solution/dong-tai-gui-hua-zhi-zui-chang-gong-gong-zi-xu-lie/    

# 动态规划
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        m = len(text1)
        n = 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][j-1],dp[i-1][j])
        return dp[-1][-1]
                  
# 递归
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        # 递归
        memo = {} #备忘录
        def dp(i, j):
            if i == -1 or j == -1:
                return 0
            if (i,j) in memo:
                return memo[(i,j)]
            if text1[i] == text2[j]:
                memo[(i,j)] = dp(i-1, j-1) + 1
            else:
                memo[(i,j)] = max(dp(i-1, j), dp(i,j-1))
            return memo[(i,j)]
        return dp(len(text1)-1,len(text2)-1)

         

*最长公共子串  

注意:与子序列不相同的是子串是连续的,子序列可以是不连续的。    

def LCS(s1,s2):
    #dp[i][j]表示以s1的i及s2的j结尾的最长公共子串长度
    #如果s1[i-1] != s2[j-1] 则,dp[i][j] = 0
    m = len(s1)
    n = len(s2)
    dp = [[0] *(n+1) for _ in range(m + 1)]
    maxLen = 0
    end = 0
    for i in range(1,m+1):
        for j in range(1,n+1):
            if s1[i-1] == s2[j-1]:
                dp[i][j] = dp[i-1][j-1] + 1
            else:
                dp[i][j] = 0
            if dp[i][j] > maxLen:
                maxLen = dp[i][j]
                end = j-1
    if maxLen == 0:
        return ''
    else:
        return s2[end - maxLen + 1:end + 1]

             

         

*最长上升子序列  

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums:
            return 0
        # dp[i]表示以第i个元素结尾的最长递增子序列长度
        n = len(nums)
        dp = [1 for _ in range(n)]
        for i in range(n):
            for j in range(i):
                if nums[i] > nums[j]:
                    dp[i] = max(dp[i],dp[j] + 1)
        return max(dp)

             

**编辑距离  

class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        # DP递推方程        
        # 存储 s1[0..i] 和 s2[0..j] 的最小编辑距离
        m = len(word1)
        n = len(word2)
        dp = [[0]*(n+1) for i in range(m+1)]
        for i in range(m+1):
            dp[i][0] = i
        for j in range(n+1):
            dp[0][j] = j
        for i in range(1, m+1):
            for j in range(1,n+1):
                if word1[i-1] == word2[j-1]:
                    dp[i][j] = dp[i-1][j-1]
                else:
                    dp[i][j] = min(dp[i-1][j]+1,
                    dp[i][j-1]+1,
                    dp[i-1][j-1]+1)
        return dp[m][n]
# 递归写法
class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
                  
        def dp(i,j):
            if i == -1:
                return j + 1
            if j == -1:
                return i + 1
            if (i,j) in memo:
                return memo[(i,j)]
            if word1[i] == word2[j]:
                memo[(i,j)] = dp(i-1,j-1)
            else:
                memo[(i,j)] = min(dp(i-1,j)+ 1,
                dp(i,j-1) + 1,
                dp(i-1,j-1) + 1)
            return memo[(i,j)]
        memo = {}
        res = dp(len(word1)-1,len(word2)-1)
        return res

             

最长重复子数组  

class Solution:
    def findLength(self, A: List[int], B: List[int]) -> int:
        # p[i][j] 表示 A[i:] 和 B[j:] 的最长公共前缀,那么答案即为所有 dp[i][j] 中的最大值。
        # 如果 A[i] == B[j],那么 dp[i][j] = dp[i + 1][j + 1] + 1,否则 dp[i][j] = 0。
        # 考虑到这里 dp[i][j] 的值从 dp[i + 1][j + 1] 转移得到,所以我们需要倒过来,首先计算 dp[len(A) - 1][len(B) - 1],最后计算 dp[0][0]
        n, m = len(A), len(B)
        dp = [[0] * (m + 1) for _ in range(n + 1)]
        ans = 0
        for i in range(n - 1, -1, -1):
            for j in range(m - 1, -1, -1):        
                dp[i][j] = dp[i + 1][j + 1] + 1 if A[i] == B[j] else 0
                ans = max(ans, dp[i][j])
        return ans

         

完全平方数  

class Solution:
    def numSquares(self, n: int) -> int:
        dp = [0] * (n + 1)
        for i in range(1, n + 1):
            dp[i] = i  #最坏的情况就是全是1
            j = 1
            while i - j*j >= 0:
                dp[i] = min(dp[i], dp[i - j * j] + 1)
                j += 1
        return dp[n]

【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总(3)https://developer.aliyun.com/article/1536620

相关文章
|
机器学习/深度学习
YOLOv8改进 | 2023注意力篇 | MLCA混合局部通道注意力(轻量化注意力机制)
YOLOv8改进 | 2023注意力篇 | MLCA混合局部通道注意力(轻量化注意力机制)
1020 1
|
6月前
|
人工智能 运维 API
OpenClaw阿里云+本地三系统部署与商业变现完整指南:大模型配置+避坑指南
OpenClaw(曾用名:Clawdbot)作为一款开源、本地优先、可长期稳定运行的AI智能体执行网关,凭借自动化任务处理、多模型兼容、技能扩展与24小时无人值守能力,成为个人低成本启动商业变现的首选工具。无需大额资金投入,无需组建团队,个人可通过技术服务、数字产品、自动化代运营、技能开发、内容付费、跨境接单、企业定制等多元路径,将AI能力转化为持续收益。
615 5
|
存储 缓存 安全
阿里云服务器计算型c7/c8y/c8i,通用型g7/g8y/g8i,内存型r7/r8y/r8i区别及选择参考
为了满足不同企业级用户的多样化需求,阿里云在当下的活动中推出了多款计算型、通用型和内存型的云服务器实例,包括计算型c7/c8y/c8i、通用型g7/g8y/g8i以及内存型r7/r8y/r8i等。这些实例各具特色,适用于不同的应用场景和业务需求。本文将为您详细解析这些实例的区别,以及选择参考,帮助您根据自己的需求选择合适的阿里云服务器实例。
|
数据采集 前端开发 API
基于Qwen2大模型实现的中药智能化筛选助手
本文介绍了利用大语言模型微调技术在中药方剂智能化筛选与优化中的应用。项目涵盖微调环境搭建、数据预处理、智能体构建及效果评估等环节,展示了模型在生成新中药方剂上的创新能力和实用性。
基于Qwen2大模型实现的中药智能化筛选助手
|
缓存 Java 测试技术
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
使用JMeter对项目各个接口进行压力测试,并对前端进行动静分离优化,优化三级分类查询接口的性能
1200 10
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
|
XML 前端开发 测试技术
【测试开花】三、项目管理-后端-实现列表接口(含分页、模糊查询)
【测试开花】三、项目管理-后端-实现列表接口(含分页、模糊查询)
【测试开花】三、项目管理-后端-实现列表接口(含分页、模糊查询)
|
负载均衡 前端开发 应用服务中间件
负载均衡指南:Nginx与HAProxy的配置与优化
负载均衡指南:Nginx与HAProxy的配置与优化
1125 3
|
数据采集 安全 大数据
隧道代理的定义与应用指南
隧道代理是一种特殊的代理服务,它允许用户通过固定的服务器IP和端口访问互联网。在这个过程中,云端服务器负责自动切换IP地址,从而实现匿名访问。这种服务使用高性能主机构建的动态IP代理服务器,使开发者无需管理IP池,降低了开发难度和部署成本。
638 1
|
传感器 监控 搜索推荐
量子科技在医疗领域的应用?
【8月更文挑战第4天】量子科技在医疗领域的应用?
1073 1
|
人工智能 自然语言处理 测试技术
Meet Llama3.1,405B赶超最强闭源模型!上魔搭社区一站体验、下载、推理、微调、部署
官方公布的Benchmark显示,Llama3.1 405B已在多项基准测试中超越GPT-4o和Claude 3.5 Sonnet,这是开源大模型首次赶超最强闭源模型!

热门文章

最新文章