题目链接:344. 反转字符串 - 力扣(Leetcode)
由于题目要求原地修改,因此必须使用双指针进行前后交换,实现反转字符串(列表形式):
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
left, right = 0, len(s) - 1
while left < right:
# left == right时中间字符不用反转
s[left], s[right] = s[right], s[left]
left += 1
right -= 1
时间复杂度是O(n)。
题目链接:541. 反转字符串 II - 力扣(Leetcode)
反转字符串进阶,其实就是限制条件多了些,分区间进行反转:
class Solution:
def reverse(self, s, start, end):
# 左闭右开区间
end -= 1
while start < end:
s[start], s[end] = s[end], s[start]
start += 1
end -= 1
def reverseStr(self, s: str, k: int) -> str:
i, n = 0, len(s)
s = list(s) # 转为字符列表(python字符串无法直接修改)
while i < n:
end = min(n, i + k)
self.reverse(s, i, end)
i += 2 * k
return ''.join(s)
通过min确定反转的右边界(注意区间的开闭特性),可以直接将最终小于k的部分也一起处理,总体时间复杂度也是O(n)。
题目链接:剑指 Offer 05. 替换空格 - 力扣(Leetcode)
基本做法是遍历一遍字符串,把对应空格按要求替换即可。Python中需要先将字符串转换为字符列表,才能做替换操作:
class Solution:
def replaceSpace(self, s: str) -> str:
s = list(s)
for i in range(len(s)):
if s[i] == ' ':
s[i] = '%20'
return ''.join(s)
利用字符串的库函数split,可以先将字符串按空格划分为 单词,再用目标字符串连接起来:
class Solution:
def replaceSpace(self, s: str) -> str:
# split方法
s = s.split()
return '%20'.join(s)
但第二种方法对一些奇奇怪怪的测试用例不管用,比如s全是空格,或者s=" 0 ",需要在代码中做一些特殊处理。
尝试用题解的扩展空间方法:
class Solution:
def replaceSpace(self, s: str) -> str:
c = s.count(' ') # 空格计数
s , n = list(s), len(s)
s.extend([' '] * c * 2)
left, right = n - 1, len(s) - 1 # left,right分别是原数组末尾和扩展后的数组末尾
while left >= 0:
if s[left] != ' ':
s[right] = s[left]
right -= 1
else:
s[right - 2: right + 1] = ['%', '2', '0']
right -= 3
left -= 1
return ''.join(s)
题目链接:151. 反转字符串中的单词 - 力扣(Leetcode)
之前做过一次题,写得比较繁琐,单独写一个函数删除多余的空格,又设了很多变量和判断条件:
class Solution:
def reverse(self, s, start, end):
while start < end:
s[start], s[end] = s[end], s[start]
start += 1
end -= 1
def remove_emptys(self, s):
slow, f = 0, 0 # 快慢指针初始化
# 去除前面多余的空格
while len(s) > 0 and f < len(s) and s[f] == ' ':
f += 1
# 去除中间多余的空格
for fast in range(f, len(s)):
if fast-1 > 0 and s[fast-1] == s[fast] and s[fast] == ' ':
continue
else:
s[slow] = s[fast]
slow += 1
# 去除最后多余的空格
if slow-1>0 and s[slow-1] == ' ':
return s[:slow-1]
else:
return s[:slow]
def reverseWords(self, s: str) -> str:
s = list(s) # python字符串不可修改,转为字符列表
s = self.remove_emptys(s)
self.reverse(s, 0, len(s)-1)
entry = False
for i in range(len(s)):
if not entry or (s[i] != ' ' and s[i-1] == ' '):
start = i
entry = True
if entry and s[i] == ' ' and s[i-1] != ' ':
end = i-1
entry = False
self.reverse(s, start, end)
if entry and i == len(s)-1 and s[i] != ' ':
end = i
entry = False
self.reverse(s, start, end)
return ''.join(s)
再次做题已经有更简洁的写法:
class Solution:
def reverseWords(self, s: str) -> str:
n = len(s)
# 去除前导空格和尾随空格
i, j = 0, n - 1
while i < n and s[i] == ' ':
i += 1
while j >= 0 and s[j] == ' ':
j -= 1
s = s[i: j+1].split() # 按空格划分
if ' ' in s:
s.remove(' ') # 删除中间所有空格
s.reverse() # 单词反转
return ' '.join(s)
简洁写法基本用库函数实现,时间效率还可以。
看题解想起来可以用整体反转+局部反转,但前提是预处理掉所有多余的空格。
题目链接:151. 反转字符串中的单词 - 力扣(Leetcode)
之前的做法直接运用python字符串切片完成:
class Solution(object):
def reverseLeftWords(self, s, n):
"""
:type s: str
:type n: int
:rtype: str
"""
return s[n:] + s[0:n]
使用整体反转+局部反转的思路:
class Solution:
def reverse(self, s, st, en):
while st < en:
s[st], s[en] = s[en], s[st]
st += 1
en -= 1
def reverseLeftWords(self, s: str, n: int) -> str:
s = list(s)
# 先整体反转,再局部反转
self.reverse(s, 0, len(s)-1)
self.reverse(s, 0, len(s)-n-1) # 反转前半段
self.reverse(s, len(s)-n, len(s)-1)
return ''.join(s)
整体和局部反转的先后顺序没有影响,时间复杂度都是O(n)。