《代码随想录》学习笔记,原链接: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)