Leetcode刷题之最长回文子串(动态规划)

1、序言

      生活:赚钱,赚更多钱,然后进入ICU,嗝屁。

2、题目

     给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"
输出:"bb"

示例 3:

输入:s = "a"
输出:"a"

示例 4:

输入:s = "ac"
输出:"a"

3、思路 

    第一种思路我还是采用双指针的方法,第一个指针控制子串的起始位置,第二个指针控制子串的终止位置,然后循环判断是否为回文子串并更新最长的回文子串。第二种思路是动态规划,是我第一种思路的时间复杂度太高导致无法通过时才学习的新方法。

3.1、思路一代码

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        if n == 0:
            return ''
        max_str = s[0]
        for i in range(n):
            for j in range(n-i):
                if s[i:i+j+1] == s[i:i+j+1][::-1] and len(s[i:i+j+1])>len(max_str):
                    max_str = s[i:i+j+1]
        return max_str

       思路一的粗暴方法行不通,接下来开始学习动态规划。

 4、动态规划

      动态规划是一种阶段性求解策略问题的数学思想。先用最简单的上台阶题分析,有n个台阶,每次只能上一个台阶或者两个台阶,问走到第n个台阶有多少种走法?

      分析:当n等于4的时候,走法图形化如下。走法有三种:

      (1)1-->2-->4

      (2)1-->3-->4

      (3)1-->2-->3-->4

    当你走到第四个台阶的时候,可能情况只有两种,一种是从2台阶上来,一种是从三台阶上来,所以就分解为两个问题:走到2有几种方法?走到3有几种方法? 所以走到4的方法等于走到2的方法加上走到3的方法。

     这时候先考虑递归,递归的核心是推衍和回溯,以及递归出口。针对本题的递归方程设计为: f(n) = f(n-1)+f(n-2)

def walk_method1(n):
    # 递归方法
    # 递归分为推演和回溯
    if n == 0:
        return 0
    if n == 1: # 递归出口
        return 1
    if n == 2:
        return 2
    return walk_method1(n-1)+walk_method1(n-2)

        但是递归的缺点是重复计算,比如走到4要计算走到2和走到3,计算走到3时又要重复计算走到2。

       这时候我们考虑使用一个哈希表,用来存储重复计算节点的结果。这就是查表的备忘录算法。

def walk_method2(n):
    # 备忘录方法
    memo = {}
    if n == 0:
        return 0
    if n == 1: # 递归出口
        return 1
    if n == 2:
        return 2
    if n in memo.keys():
        return memo[n]
    else:
        value = walk_method1(n-1)+walk_method1(n-2)
        memo[n] = value
        return value

        递归或者备忘录算法是自顶向下,然后再自底向上。这时候我们思考为啥不直接从底部直接上到顶部?动态规范的核心是:最优子结构,边界,状态转移公式。f(2)和f(3)是f(4)的最优子结构,f(1)和f(2)是问题的边界,状态转移公式是 f(n) = f(n-1)+f(n-2)。我们开始由1和2状态得到3状态,再忘记1状态,更新到2状态和3状态得到4状态就得到f(4),这就是简单的动态规划思想。

def walk_method3(n):
    step1 = 1
    step2 = 2
    tmp = 0
    for i in range(n-2):
        #从第三个台阶开始计算
        tmp = step1 + step2
        #更新状态
        step1 = step2
        step2 = tmp
    return tmp

     让我们再来一个难一点的动态规划题目,国王和金矿:有一个国家发现了5座金矿,每座金矿的黄金储量不同,需要参与挖掘的工人数也不同。参与挖矿工人的总数是10人。每座金矿要么全挖,要么不挖,不能派出一半人挖取一半金矿。要求用程序求解出,要想得到尽可能多的黄金,应该选择挖取哪几座金矿?答案参考链接https://www.sohu.com/a/149075950_684445?spm=smpc.content.share.1.1615368141569lixrfPF#comment_area,我实在是看不下去了,脑壳有点疼。

 

      

5、解题

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):
                j = i + l
                if j >= len(s):
                    break
                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

这是其他人提交的动态规划,结果我还是超时,我放弃这这个题了。学了个寂寞。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超超爱AI

土豪请把你的零钱给我点

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值