2021-08-09 字符串:回文串

验证回文串

  • 筛选+判断:
class Solution:
    def isPalindrome(self, s: str) -> bool:
        s = "".join(ch.lower() for ch in s if ch.isalnum())
        return s == s[::-1]
  • 双指针:
class Solution:
    def isPalindrome(self, s: str) -> bool:
        s = "".join(ch.lower() for ch in s if ch.isalnum())
        n = len(s)
        left, right = 0, n-1

           while left < right:
                if s[left] != s[right]:
                    return False
                left, right = left+1, right-1
            return True

  • 原字符串判断:
class Solution:
    def isPalindrome(self, s: str) -> bool:
        n = len(s)
        left, right = 0, n-1

        while left < right:
            # 用while是因为不止一个,and后条件是因为可能都不是数字或字母,一定要充分测试
            while not s[left].isalnum() and left < right:
                left += 1
            while not s[right].isalnum() and left < right:
                right -= 1
            if s[left].lower() != s[right].lower():
                return False
            left, right = left+1, right-1
        return True
  • 正则表达式:
class Solution:
    def isPalindrome(self, s: str) -> bool:
        s = re.findall(r"[a-zA-Z0-9]", s)
        s = "".join(s)
        return s[::-1] == s

分割回文串:验证+分割子串

  • 回溯+动态规划:
class Solution:
    def partition(self, s: str):
        n = len(s)
        f = [[True] * n for _ in range(n)]
        # 注意动归方向
        for i in range(n - 1, -1, -1):
            for j in range(i + 1, n):
                f[i][j] = (s[i] == s[j]) and f[i + 1][j - 1]

        ret = list()
        ans = list()

        def dfs(i: int):
            if i == n:
                ret.append(ans[:])
                return
            for j in range(i, n):
                if f[i][j]:
                    ans.append(s[i:j+1])
                    dfs(j+1)
                    ans.pop()
        dfs(0)
        return ret
  • 回溯+记忆化搜索
class Solution:
    def partition(self, s: str) -> List[List[str]]:
        n = len(s)

        ret = list()
        ans = list()

        @cache
        def isPalindrome(i: int, j: int) -> int:
            if i >= j:
                return 1
            return isPalindrome(i + 1, j - 1) if s[i] == s[j] else -1

        def dfs(i: int):
            if i == n:
                ret.append(ans[:])
                return

            for j in range(i, n):
                if isPalindrome(i, j) == 1:
                    ans.append(s[i:j+1])
                    dfs(j + 1)
                    ans.pop()

        dfs(0)
        isPalindrome.cache_clear()
        return ret

最长回文串:分割子串+验证

  • 暴力解法:即两个for循环遍历所有情况
  • 中心扩散:
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 longestPalindrome(self, s: str) -> str:
        n = len(s)
        if n < 2:
            return s

        max_len = 1
        dp = [[False]*n for _ in range(n)]
        for i in range(n):
            dp[i][i] = True

        for j in range(1, n):
            for i in range(j):
                if j-i <= 2:
                    if s[i] == s[j]:
                        dp[i][j] = True
                        cur_len = j-i+1
                else:
                    if s[i] == s[j] and dp[i+1][j-1]:
                        dp[i][j] = True
                        cur_len = j-1+1
                        
                if dp[i][j]:
                    if cur_len > max_len:
                        max_len = cur_len
# 有点难,改天来
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值