leetcod中常见的字符串问题总结(python)

Z字形变换

题目描述:将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
思路分析
(1)创建一个二维矩阵,模拟Z字形读取字符串的过程,最后在按行遍历矩阵。
(2)我们发现遍历字符串s的时候对应字符在Z字形中行索引的变化是从0到n再从n到0,那么按照行索引的变化,将每个字符填入相应的行就行了。可以发现的是,行索引在行为0或者n时才会变化,其他地方不变。

思路1代码

class Solution:
    def convert(self, s: str, numRows: int) -> str: 
        if not s:return ""
        if numRows==1:return s
        m = numRows 
        n = (len(s)//(1+m-2) + 1)*(1+m-2)
        matrix = [[0]*n for _ in range(m)]
        i, j = 0, 0
        p = 1+m-2
        for v in s:
            if i<m-1 and j%p==0:
                matrix[i][j]=v
                i += 1
            elif i==m-1 and j%p==0:
                matrix[i][j]=v
                i -= 1
                j += 1
            elif j%p !=0:
                matrix[i][j]=v
                i -= 1
                j += 1
            else:return
        res = ""
        for i in range(len(matrix)):
            for j in range(len(matrix[0])):
                if matrix[i][j]!=0:
                    res += matrix[i][j]
        return res

思路2代码

class Solution:
    def convert(self, s: str, numRows: int) -> str: 
        if numRows<2:return s
        res = ["" for _ in range(numRows)]
        
        i, flag = 0, -1 #falg用来表示行索引是增还是减
        for v in s:
            res[i] += v
            if i==0 or i==numRows-1:flag = -flag
            i += flag
        return "".join(res)

模型匹配

题目描述:你有两个字符串,即pattern和value。 pattern字符串由字母"a"和"b"组成,用于描述字符串中的模式。例如,字符串"catcatgocatgo"匹配模式"aabab"(其中"cat"是"a",“go"是"b”),该字符串也匹配像"a"、"ab"和"b"这样的模式。但需注意"a"和"b"不能同时表示相同的字符串。编写一个方法判断value字符串是否匹配pattern字符串。
示例 1:
输入: pattern = “abba”, value = “dogcatcatdog”
输出: true
示例 2:
输入: pattern = “abba”, value = “dogcatcatfish”
输出: false

基本思路:(1)先统计pattern每个字母a,b的个数,如果能匹配成功那么 a字母的数量a字母匹配长度 + b字母的数量b字母匹配的长度 = value的长度。
(2)那么我们列举所有的字母a和字母b匹配的长度的可能的情况
(3)对于每一种情况,遍历patter遇到a,则取出value对应长度的字符串放入集合中,如果下一次又遇到a,匹配的字符串跟集合中不同,则说明匹配失败,否则继续,遍历到b也是一样
(4)最后判断字母a和字母b匹配的字符串是否相等。

class Solution:
    def patternMatching(self, pattern: str, value: str) -> bool:
        n_a, n_b = pattern.count("a"), pattern.count("b")
        if n_a == 0 and n_b==0:
            return not value 
        if n_a == 0:
            return (len(value)%n_b==0) and n_b*value[:len(value)//n_b] == value
        if n_b == 0:
            return (len(value)%n_a==0) and n_a*value[:len(value)//n_a] == value

        candidate = []
        m = len(value)//n_a
        for i in range(0, m+1):
            if (len(value)-i*n_a)%n_b == 0:
                candidate.append([i, (len(value)-i*n_a)//n_b])
        
        for i,j in candidate:
            if self.check(pattern, value, i, j):
                return True
        return False

    def check(self, pattern, value, i, j):
        set1 = set()
        set2 = set()
        for c in pattern:
            if c == 'a':
                if set1 and value[:i] not in set1:
                    return False
                set1.add(value[:i])
                value = value[i:]
            elif c == 'b':
                if set2 and value[:j] not in set2:
                    return False
                set2.add(value[:j])
                value = value[j:]
        if set1 == set2:        ## a,b对应模式相同返回False
            return False
        return True

至少有k个重复字符的最长子串

题目描述:找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。
输入:
s = “aaabb”, k = 3
输出:
3
最长子串为 “aaa” ,其中 ‘a’ 重复了 3 次。

基本思路:字符串S中出现次数小于k次的一定不会出现在最长子串T中,那么就可以根据不会出现在字符串中的字符将字符串S分成几个部分,然后在每个部分重复上述过程,直到子串所有字符均满足要求,

代码如下

class Solution:
    def longestSubstring(self, s: str, k: int) -> int:
        if len(s)<k:
            return 0
        
        min_char = min(set(s), key=s.count)

        if s.count(min_char)>=k:
            return len(s)
        return max(self.longestSubstring(a,k) for a in s.split(min_char))

通配符匹配

给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。

‘?’ 可以匹配任何单个字符。
‘*’ 可以匹配任意字符串(包括空字符串)。
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *

基本思路:动态规划

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m, n = len(s), len(p)
        dp = [[False]*(n+1) for _ in range(m+1)]
        dp[0][0] = True
        for j in range(1,n+1):
            if p[j-1]=="*":
                dp[0][j] = dp[0][j-1]
        for i in range(1,m+1):
            for j in range(1,n+1):
                if s[i-1]==p[j-1] or p[j-1]=="?":
                    dp[i][j] = dp[i-1][j-1]
                elif p[j-1]=="*":
                    dp[i][j] = dp[i-1][j] or dp[i][j-1]
        return dp[-1][-1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值