字符串
1.反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
双指针 直接秒
def reverseString(self, s: List[str]) -> None:
if s is None :
return
n = len(s)
l,r = 0,n - 1
while l < r:
temp = s[l]
s[l] = s[r]
s[r] = temp
l += 1
r -= 1
2.反转字符串 II
def reverseStr(self, s: str, k: int) -> str:
n = len(s)
cnt = (n // (2 * k)) + 1
re = list(s)
for i in range(cnt):
#l,r = -1,-1
#if i*2*k+k <= n:
# l = i*2*k
# r = i*2*k+k-1
#else:
# l = i * 2 * k
# r = n - 1
l, r = i * 2 * k, min(i * 2 * k + k - 1, n - 1)
while l < r:
re[l],re[r] = re[r],re[l]
l += 1
r -= 1
return ''.join(re)
3.替换空格
请实现一个函数,把字符串
s
中的每个空格替换成"%20"。
不使用额外的辅助空间
def replaceSpace(self, s: str) -> str:
cnt = s.count(" ")
res = list(s)
res.extend([' ']*cnt*2)
l,r = len(s) - 1,len(res) - 1
while l >= 0:
if s[l] == " ":
res[r-2:r+1] = "%20"
r -= 3
else:
res[r] = res[l]
r -= 1
l -= 1
return "".join(res)
4.反转字符串中的单词(2)
最直接的思路
def reverseWords(self, s: str) -> str:
return ' '.join(s.strip().split()[::-1])
不使用额外的空间
去除多余空格
翻转整个字符串
将每个单词翻转
def reverseWords(self, s: str) -> str:
def reverse(temp,l,r):
while l < r:
temp[l], temp[r] = temp[r], temp[l]
l += 1
r -= 1
n = len(s)
l,r = 0,n - 1
temp = []
while l <= r and s[l] == ' ':
l += 1
while l <= r and s[r] == ' ':
r -= 1
while l <= r:
if s[l] != ' ':
temp.append(s[l])
elif temp[-1] != ' ':
temp.append(s[l])
l += 1
# 翻转字符串
l,r = 0,len(temp) - 1
reverse(temp,l,r)
# 翻转每个单词
l,r = 0,0
n = len(temp)
while l < n:
while r < n and temp[r] != ' ':
r += 1
reverse(temp,l,r - 1)
r += 1
l = r
return ''.join(temp)
5.左旋转字符串
使用切片
不使用切片
def reverseLeftWords(self, s: str, n: int) -> str:
s = list(s)
s[:n] = list(reversed(s[:n]))
s[n:] = list(reversed(s[n:]))
s.reverse()
return ''.join(s)
6.实现 strStr()(2)
KMP
举例: a a b a a f
前缀表next 0 1 0 1 2 0
前缀表之和模式串有关
def strStr(self, haystack: str, needle: str) -> int:
# 获取模式串的next数组(KMP的核心)
def getNext(next,s):
next[0] = 0
j = 0
# j 指向前缀末尾位置, i 指向后缀末尾位置
# 采用0 1 0 1 2 0
# 每次回退取前一位的next值
for i in range(1, len(s)):
while j > 0 and s[i] != s[j]: # 前缀和后缀不相等,回退
j = next[j - 1]
if s[i] == s[j]: # 上面退出while可能是因为j == 0或者s[i] == s[j],所以这里还要再判断一下
j += 1
next[i] = j # next[i]的值就是j,前缀的长度
next = [-1] * len(needle)
getNext(next,needle)
i,j = 0,0
while i < len(haystack) and j < len(needle):
while j > 0 and haystack[i] != needle[j]:
j = next[j - 1]
if haystack[i] == needle[j]: # 这里要么是中途能续上(如aab),要么模式串从头开始
j += 1
i += 1
return i - j if j == len(needle) else -1
7.重复的子字符串(2)
给定一个非空的字符串
s
,检查是否可以通过由它的一个子串重复多次构成。这道题绝对不止简单题的难度
移动匹配
字符串:s+s(掐头去尾)
模式串:s
def repeatedSubstringPattern(self, s: str) -> bool:
n = len(s)
def getNext(next,st):
j = 0
for i in range(1,len(st)):
while j > 0 and st[i] != st[j]:
j = next[j - 1]
if st[i] == st[j]:
j += 1
next[i] = j
next = [0]*n
getNext(next,s)
i,j = 0,0
# h:匹配串 s:模式串
# 原字符串掐头去尾
h = (s+s)[1:2*len(s)-1]
while i < len(h) and j < len(s):
while j > 0 and s[j] != h[i]:
j = next[j - 1]
if s[j] == h[i]:
j += 1
i += 1
return j == len(s)
最小重复字串
ababab ab
ab ababab
next: 0 0 1 2 3 4 5 6
若next[n-1]!=0 && len(s)%(len(s)-next[n-1])==0,说明满足题设条件
def repeatedSubstringPattern(self, s: str) -> bool:
n = len(s)
def getNext(next,st):
j = 0
for i in range(1,len(st)):
while j > 0 and st[i] != st[j]:
j = next[j - 1]
if st[i] == st[j]:
j += 1
next[i] = j
next = [0]*n
getNext(next,s)
return True if next[n - 1] != 0 and (n % (n - next[n - 1]) == 0) else False