力扣刷题笔记 字符串及其相关题目(含ACM模式)

文章介绍了Python中各种字符串操作,如反转字符串、使用KMP算法查找子串、替换数字、单词反转、右旋字符串以及检测重复字符串模式。核心代码展示了如何实现这些功能,并且区分了ACM模式和核心代码模式的区别。
摘要由CSDN通过智能技术生成

 《代码随想录》学习笔记,原链接:https://programmercarl.com/

344.反转字符串

  • 核心代码模式
class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        lenth = len(s)
        for i in range(lenth // 2):
            s[i], s[lenth - i - 1] = s[lenth - i - 1], s[i]     # 只能在一行之内这么写,不然s[i]的值会被覆盖
                    
        return str(s)

【注】 如果将

s[i], s[lenth - i - 1] = s[lenth - i - 1], s[i] 

改为

s[i] = s[lenth - i - 1]

s[lenth - i - 1] = s[i]

则会报错:

  • ACM模式
class Solution:
    def reverseString(self, s):
        """
        Do not return anything, modify s in-place instead.
        """
        lenth = len(s)
        for i in range(lenth // 2):
            s[i], s[lenth - i - 1] = s[lenth - i - 1], s[i]  # 只能在一行之内这么写,不然s[i]的值会被覆盖

        return str(s)

# 输入要反转的字符串
string = input("输入字符串s:")
s = []

for i in string:
    s.append(i)

# 反转字符串
solution = Solution()
result = solution.reverseString(s)
print(result)

【注】将字符串分割成单个字母组成的列表,不可以使用input("输入字符串s:").split(""),否则会报错:“ValueError: empty separator”。

原因:split()方法可以使用指定字符将字符串分割,生成一个字符串列表。当字符串中不包含分隔符或者split()方法中没有提供分隔符,则会生成由原字符串组成的只有一个元素的列表。但是,split()方法中的分隔符可以省略,却不可以使用空字符串,即("")作为分隔符,否则就会出现报错:“ValueError: empty separator”。

541.反转字符串II

  •  核心代码模式
class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        i =  0
        string_list = list(s)   # 将字符串转成列表,方便后续使用reversed函数进行反转
        lenth = len(string_list)    

        while i < lenth:
            if i + k <= lenth:  # 对前k个字符进行反转
                string_list[i: i + k] = reversed(string_list[i: i + k])     # 注意左开右闭,范围为[i: i + k]
            else:       # 对剩余字符进行反转
                string_list[i: lenth] = reversed(string_list[i: lenth])     # 注意左开右闭,范围为[i: lenth]
            
            i += k * 2  
        
        s = ''.join(string_list)    # 将列表整合成字符串

        return s

 【注】reversed()函数只能处理列表,因此需要先进行字符串到列表的变换。

  • ACM模式
class Solution:
    def reverseStr(self, s, k):
        i = 0
        string_list = list(s)  # 将字符串转成列表,方便后续使用reversed函数进行反转
        lenth = len(string_list)

        while i < lenth:
            if i + k <= lenth:  # 对前k个字符进行反转
                string_list[i: i + k] = reversed(string_list[i: i + k])  # 注意左开右闭,范围为[i: i + k]
            else:  # 对剩余字符进行反转
                string_list[i: lenth] = reversed(string_list[i: lenth])  # 注意左开右闭,范围为[i: lenth]

            i += k * 2

        s = ''.join(string_list)  # 将列表整合成字符串

        return s

# 输入要反转的字符串和k
s = input("输入字符串s:")
k = int(input("输入k:"))

# 反转字符串II
solution = Solution()
result = solution.reverseStr(s, k)
print(result)

替换数字

卡码网题目链接

 

 

  • ACM模式
class Solution:
    def replaceNumber(self, s: str) -> str:
        s = list(s)  # 将字符串s转换成字符列表
        str_lenth = len(s)  # 记录原字符串长度
        record = list("number")  # 将要填充的字符串储存成列表

        # 统计数字字符的个数
        num_count = 0
        for i in s:
            if ord(i) - ord("0") in range(10):
                num_count += 1

        # 扩展字符串列表s的长度,直接使用 + 运算符添加新列表的元素。行为类似于我们修改变量值的方式
        s = s + [0] * (num_count * 5)

        # 双指针法
        slow, fast = str_lenth - 1, len(s) - 1
        while slow >= 0:
            if ord(s[slow]) - ord("0") in range(10):
                for i in range(5, -1, -1):
                    s[fast] = record[i]
                    fast -= 1
            else:
                s[fast] = s[slow]
                fast -= 1
            slow -= 1

        s = ''.join(s)
        return s


s = input("")
solution = Solution()
result = solution.replaceNumber(s)
print(result)

 151.反转字符串中的单词

先删除空白生成单词列表,然后单词反转输出。 因为字符串是不可变类型,所以反转单词的时候,需要将其转换成列表,然后通过join函数再将其转换成列表,所以空间复杂度不是O(1)。

  •  核心代码模式
class Solution:
    def reverseWords(self, s: str) -> str:
        record = s.split()      # 去除字符串内部和两端的多余空格,注意split函数括号内要为空,不能使用split(" "),否则遇到多个连续空格只会去除其中一个
        result = " ".join(record[::-1]) # 将去除空格后的结果,使用空格倒序连接成字符串

        return result
  • ACM模式
class Solution:
    def reverseWords(self, s: str) -> str:
        record = s.split()      # 去除字符串内部和两端的多余空格,注意split函数括号内要为空,不能使用split(" "),否则遇到多个连续空格只会去除其中一个
        result = " ".join(record[::-1]) # 将去除空格后的结果,使用空格倒序连接成字符串

        return result

# 输入单词字符串
s = input("输入要修改的字符串s:")

# 反转字符串中的单词
solution = Solution()
result = solution.reverseWords(s)
print(result)

55.右旋字符串(第八期模拟笔试)

  • ACM模式 
class Solution:
    def rotString(self, s: str, k: int) -> str:
        s = list(s)  # 将字符串拆分成字符列表
        lenth = len(s)
        
        s = s + [0] * (lenth - k)  # 扩容lenth - k个元素
        s[lenth:] = s[: lenth - k]  # 将前面lenth - k个元素按顺序存储到新扩容的部分

        result = ''.join(s[lenth - k:])     # 将右旋后的结果拼接成字符串

        return result

# 自定义输入k和字符串s
k = int(input())
s = input()

# 右旋字符串
solution = Solution()
result = solution.rotString(s, k)
print(result)
  • 不申请额外空间(ACM模式) 

(1)先根据k将字符串分割成两个部分

(2)对字符串s进行整体反转

(3)对每个部分再次进行反转,得到最终结果的列表形式

 

class Solution:
    def rotString(self, s, k):
        s = list(s)  # 将字符串拆分成字符列表

        # 整体反转字符串
        s = list(reversed(s))   # reversed()方法返回一个反转元素顺序的迭代器,要将其转换为列表
        
        # 分别反转两个部分的字符串
        s[0: k] = list(reversed(s[0: k]))   # reversed()方法返回一个反转元素顺序的迭代器,要将其转换为列表
        s[k: len(s)] = list(reversed(s[k: len(s)]))     # reversed()方法返回一个反转元素顺序的迭代器,要将其转换为列表

        # 将反转结果拼接成字符串
        result = ''.join(s)

        return result

# 自定义输入k和字符串s
k = int(input())
s = input()

# 右旋字符串
solution = Solution()
result = solution.rotString(s, k)
print(result)

28.找出字符串中第一个匹配项的下标

  • KMP算法

  • 核心代码模式
class Solution:
    # 构建前缀表next
    def get_next(self, s: str) -> None:
        next = [0] * len(s)     # 创建前缀表
        j = 0       # 初始化相等前后缀长度
        next[0] = 0     # 前缀表的第一个元素为0

        for i in range(1, len(s)):
            while j > 0 and s[i] != s[j]:
                j = next[j - 1]     # 若i和j对应的s元素不相同,则j回退到next[j - 1]代表的位置
            if s[i] == s[j]:
                j += 1      # 若i和j对应的s元素相同,则i和j均+1,注意对于每一个i,j只可能有一次+1操作,但可能有很多次回退操作
            
            next[i] = j     # 得到当前位置前缀表的元素值
    
        return next     # 返回前缀表next
    
    # 匹配字符串
    def strStr(self, haystack: str, needle: str) -> int:
        j = 0       # 初始化neddle开始匹配的位置

        if len(needle) == 0:        # 特殊情况判断
            return 0
        
        next = self.get_next(needle)        # 获取前缀表next

        for i in range(len(haystack)):
            while j > 0 and haystack[i] != needle[j]:
                j = next[j - 1]     # 如果i和j对应的元素不相同,则j回退到next[j - 1]的位置,注意,这里i和j分别时连个不同字符串的下标
            if haystack[i] == needle[j]:
                j += 1      # 如果i和j代表的元素相同,则i和j都+1,注意对于每个i,只会进行一次j+1的操作
            if j == len(needle):
                return i - j + 1        # 匹配成功,返回第一个匹配项的下标
        
        return -1       # 匹配失败
        
  • ACM模式
class Solution:
    # 构建前缀表next
    def get_next(self, s: str) -> None:
        next = [0] * len(s)  # 创建前缀表
        j = 0  # 初始化相等前后缀长度
        next[0] = 0  # 前缀表的第一个元素为0

        for i in range(1, len(s)):
            while j > 0 and s[i] != s[j]:
                j = next[j - 1]  # 若i和j对应的s元素不相同,则j回退到next[j - 1]代表的位置
            if s[i] == s[j]:
                j += 1  # 若i和j对应的s元素相同,则i和j均+1,注意对于每一个i,j只可能有一次+1操作,但可能有很多次回退操作

            next[i] = j  # 得到当前位置前缀表的元素值

        return next  # 返回前缀表next

    # 匹配字符串
    def strStr(self, haystack: str, needle: str) -> int:
        j = 0  # 初始化neddle开始匹配的位置

        if len(needle) == 0:  # 特殊情况判断
            return 0

        next = self.get_next(needle)  # 获取前缀表next

        for i in range(len(haystack)):
            while j > 0 and haystack[i] != needle[j]:
                j = next[j - 1]  # 如果i和j对应的元素不相同,则j回退到next[j - 1]的位置,注意,这里i和j分别时连个不同字符串的下标
            if haystack[i] == needle[j]:
                j += 1  # 如果i和j代表的元素相同,则i和j都+1,注意对于每个i,只会进行一次j+1的操作
            if j == len(needle):
                return i - j + 1  # 匹配成功,返回第一个匹配项的下标

        return -1  # 匹配失败


# 自定义输入字符串haystack和needle
haystack = input("haystack:")
needle = input("needle:")

# 找出字符串中第一个匹配项的下标
solution = Solution()
result = solution.strStr(haystack, needle)
print(result)

459.重复字符串

  • 核心代码模式
class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        next = [0] * len(s)     # 初始化前缀表next
        j = 0       # 初始化最长相等前后缀长度

        for i in range(1, len(s)):      # 获取前缀表next
            while j > 0 and s[i] != s[j]:
                j = next[j - 1]     # 若i和j对应的s元素不相同,则j回退到next[j - 1]代表的位置
            if s[i] == s[j]:
                j += 1      # 若i和j对应的s元素相同,则i和j均+1,注意对于每一个i,j只可能有一次+1操作,但可能有很多次回退操作
            next[i] = j     # j的取值即为当前i位置的前缀表的元素值
        
        """
            首先判断next的最后一个元素不为0,如果为0则一定不重复
            其次,如果字符串s重复,则next的最大值一定取到最后一个元素位置,所以使用len(s) - next[-1]
        """
        if next[-1] != 0 and len(s) % (len(s) - next[-1] ) == 0:      # 判断字符串是否重复  
            return True
        
        return False
            

【注】由于题目中给出1 <= s.lenth <= 10000,所以不需要进行s是否为空的特殊判断。

  • ACM模式
class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        next = [0] * len(s)  # 初始化前缀表next
        j = 0  # 初始化最长相等前后缀长度

        for i in range(1, len(s)):  # 获取前缀表next
            while j > 0 and s[i] != s[j]:
                j = next[j - 1]  # 若i和j对应的s元素不相同,则j回退到next[j - 1]代表的位置
            if s[i] == s[j]:
                j += 1  # 若i和j对应的s元素相同,则i和j均+1,注意对于每一个i,j只可能有一次+1操作,但可能有很多次回退操作
            next[i] = j  # j的取值即为当前i位置的前缀表的元素值

        """
            首先判断next的最后一个元素不为0,如果为0则一定不重复
            其次,如果字符串s重复,则next的最大值一定取到最后一个元素位置,所以使用len(s) - next[-1]
        """
        if next[-1] != 0 and len(s) % (len(s) - next[-1]) == 0:  # 判断字符串是否重复
            return True

        return False


# 自定义输入字符串s
s = input("s:")

# 重复字符串
solution = Solution()
result = solution.repeatedSubstringPattern(s)
print(result)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值