文章目录
一、反转
(一)反转字符串
数组反转就用首尾指针,字符串是一种特殊的数组结构
- 【反转问题】字符串也是一种数组结构,不同于链表,链表交换是从开始到最后两两交换,相当于调换一下指针的方向;但是字符串的交换则是分别从头尾出发,两两交换头尾元素。
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
#s.reverse()
left,right=0,len(s)-1
while left<right: # 知道首尾指针相撞才结束循环
s[left],s[right]=s[right],s[left]
left+=1
right-=1
return s
(二)间隔反转字符串
541. 反转字符串 II
在反转字符串的基础上每隔两个字母做反转
class Solution:
def reverseStr(self, s: str, k: int) -> str:
a = list(s)
for i in range(0, len(a), 2*k): #间隔2k,变的只有前k个
a[i:i+k] = reversed(a[i:i+k]) #list[a:b]b越界了就取不到呗
return "".join(a)
(三)反转字符串中的单词
【法一】利用python已有的函数API
-
python中翻转列表的三种方式:
1.list_b=reversed(list_b) 2.list_a.reverse() 3.list_b=list_a[::-1]
# 法一:直接反转
class Solution:
def reverseWords(self, s: str) -> str:
return ' '.join([i for i in s.split(' ')[::-1] if i != '']) # 用生成器对列表中的元素做筛选
class Solution:
def reverseWords(self, s: str) -> str:
return ' '.join([i for i in reversed(s.split(' ')) if i != '']) # 用生成器对列表中的元素做筛选
【法二】自己定义函数
这里的代码有很多注意点:
- 多个连续的空格,只保留第一个:遍历,cur空格且上一个不是,则记录,否则continue
- 翻转字符串中的每个字符:先定义一个翻转函数,遍历一直到有空格,将遍历的序列进行翻转。更新start和end指针继续搜索从非空到非空的序列。
class Solution:
# 1.去除多余的空格
def trim_spaces(self,s):
n=len(s)
left=0
right=n-1
while left<=right and s[left]==' ': # 去除开头的空格
left+=1
while left<=right and s[right]==' ': # 去除结尾的空格
right-=1
tmp=[]
while left<=right: # 去除单词中间多余的空格
if s[left]!=' ':
tmp.append(s[left])
elif tmp[-1]!=' ': # 只保留第一个空格
tmp.append(s[left])
left+=1
return tmp
# 2.翻转字符数组
def reverse_string(self,nums,left,right):
while left<=right:
nums[left], nums[right]=nums[right],nums[left]
left+=1
right-=1
return None # 返回的变量和作用的参数是同一个,所以只用None记录变化情况就可以了,当然也可以return l记录新变量,但是没有必要哦
# 3.翻转字符串中的每个单词
def reverse_each_word(self, nums):
start=0
end=0
n=len(nums)-1
while start<=n:
while end<=n and nums[end]!=' ':
end+=1
self.reverse_string(nums,start,end-1)
start=end+1
end+=1
return None
# 4.实例化
def reverseWords(self, s): #测试用例:"the sky is blue"
l = self.trim_spaces(s)
self.reverse_string( l, 0, len(l) - 1)
self.reverse_each_word(l)
return ''.join(l)
(四)部分反转字符串中的单词
# 方法一:可以使用切片方法
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
return s[n:] + s[0:n]
# 方法二:reverse()
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
s = list(s)
s[0:n] = list(reversed(s[0:n]))
s[n:] = list(reversed(s[n:]))
s.reverse()
return "".join(s)
# 方法三:如果连reversed也不让使用,那么自己手写一个
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
def reverse_sub(lst, left, right):
while left < right:
lst[left], lst[right] = lst[right], lst[left]
left += 1
right -= 1
res = list(s)
end = len(res) - 1
reverse_sub(res, 0, n - 1)
reverse_sub(res, n, end)
reverse_sub(res, 0, end)
return ''.join(res)
# 同方法二
# 时间复杂度:O(n)
# 空间复杂度:O(n),python的string为不可变,需要开辟同样大小的list空间来修改
二、替换
-
代码技巧:append & + & extend
1.append命令可以添加单个元素,也可以添加可迭代对象;而extend命令只能添加可迭代对象,也就是一个个添加。 2.extend不占用新内存,而+会占用新内存
-
【替换问题】(1)replace(2)从前向后遍历,但是占用空间复杂度高(3)先填充再从后向前填充,占用的空间少。
-
【 填充问题】:很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
这么做有两个好处: 1.不用申请新数组。 2.从后向前填充元素,避免了从前先后填充元素要来的 每次添加元素都要将添加元素之后的所有元素向后移动。
# s.replace(' ','%20)
class Solution:
def replaceSpace(self, s: str) -> str:
# 填充空格
counter = s.count(' ')
res = list(s)
res.extend([' '] * counter * 2) # 每碰到一个空格就多拓展两个格子,1 + 2 = 3个位置存’%20‘
# 双指针从后往前替换
left, right = len(s) - 1, len(res) - 1
for i in range(left,-1,-1): # 倒叙循环,左闭右开,两个-1很容易写错
if res[i] != ' ':
res[right] = res[i]
right -= 1
else:
res[right - 2],res[right-1],res[right]= '%','2','0' # res[right - 2: right + 1] = '%20'
right -= 3
left-=1
return ''.join(res)
三、字符串匹配——KMP
-
主要思想:当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。
-
具体理解:
1、概念 (1)next数组就是一个前缀表(prefix table):前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。具体实现,next数组即可以就是前缀表,也可以是前缀表统一减一(右移一位,初始位置为-1) (2)前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串。 (3)后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。 2、思路: (1)前缀表要求的就是相同前后缀的长度。因为找到了最长相等的前缀和后缀,匹配失败的位置是后缀子串的后面,那么我们找到与其相同的前缀的后面从新匹配就可以了。 (2)前缀表的计算 找到的不匹配的位置, 那么此时我们要看它的前一个字符的前缀表的数值是多少,也就是前面字符串的最长相同的前缀和后缀。把下标移动到对应的索引位置继续比配。 3、时间复杂度: O(n+m) 4、操作步骤: (1)构造next数组:1️⃣初始化定义两个指针i和j,j指向前缀起始位置,i指向后缀起始位置。j=-1,next[0]=j。
28. 实现 strStr()
字符串a是否是字符串b的子串
459. 重复的子字符串