344. 反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
题目链接:链接
自己理解题目:首先想到的是reverse,其次是s[::-1],都是取巧的办法,然后看答案,说是可以用双指针,然后才恍然大悟。
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
left=0
right=len(s)-1
while left<=right:
tmp=s[left]
s[left]=s[right]
s[right]=tmp
left+=1
right-=1
参考答案:
class Solution:#双指针法
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
left, right = 0, len(s) - 1
# 该方法已经不需要判断奇偶数,经测试后时间空间复杂度比用 for i in range(len(s)//2)更低
# 因为while每次循环需要进行条件判断,而range函数不需要,直接生成数字,因此时间复杂度更低。推荐使用range
while left < right:
s[left], s[right] = s[right], s[left]
left += 1
right -= 1
class Solution:#使用栈
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
stack = []
for char in s:
stack.append(char)
for i in range(len(s)):
s[i] = stack.pop()
class Solution:#使用range
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
n = len(s)
for i in range(n // 2):
s[i], s[n - i - 1] = s[n - i - 1], s[i]
class Solution:#用reverse
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
s[:] = reversed(s)
class Solution:#使用切片
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
s[:] = s[::-1]
class Solution:#使用列表推导
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
s[:] = [s[i] for i in range(len(s) - 1, -1, -1)]
反思总结:数组,链表,字符串的常用方法:双指针法,前面的学了小白又忘了,必须复习啊。字符串反转的方法有很多,自己的思路不够开阔,多学多看多码代码。
541. 反转字符串 II
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
题目链接:链接
自己理解题目:说实话题目的示例我没看太懂
参考答案:
class Solution:
def reverseStr(self, s: str, k: int) -> str:
"""
1. 使用range(start, end, step)来确定需要调换的初始位置
2. 对于字符串s = 'abc',如果使用s[0:999] ===> 'abc'。字符串末尾如果超过最大长度,则会返回至字符串最后一个值,这个特性可以避免一些边界条件的处理。
3. 用切片整体替换,而不是一个个替换.
"""
def reverse_substring(text):
left, right = 0, len(text) - 1
while left < right:
text[left], text[right] = text[right], text[left]
left += 1
right -= 1
return text
res = list(s)
for cur in range(0, len(s), 2 * k):#2k步长循环反转
res[cur: cur + k] = reverse_substring(res[cur: cur + k])#只反转前k个字符
return ''.join(res)
class Solution:
def reverseStr(self, s: str, k: int) -> str:
# Two pointers. Another is inside the loop.
p = 0#记录前K个字符的起始位置
while p < len(s):
p2 = p + k #记录前K个字符的结束位置
# Written in this could be more pythonic.
s = s[:p] + s[p: p2][::-1] + s[p2:]#前k个字符切片反转
p = p + 2 * k
return s
反思总结:题目本质不复杂,在反转字符串的基础上附加了区间反转条件。
剑指 Offer 05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"
题目链接:链接
自己理解题目:遍历字符串,判断空字符则替换。但是因为字符串是不可变类型,所以操作字符串需要将其转换为列表,因此空间复杂度不可能为O(1)。
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)
参考答案:
(版本一)转换成列表,并且添加相匹配的空间,然后进行填充
class Solution:
def replaceSpace(self, s: str) -> str:
counter = s.count(' ')
res = list(s)
# 每碰到一个空格就多拓展两个格子,1 + 2 = 3个位置存’%20‘
res.extend([' '] * counter * 2)
# 原始字符串的末尾,拓展后的末尾
left, right = len(s) - 1, len(res) - 1
while left >= 0:
if res[left] != ' ':
res[right] = res[left]
right -= 1
else:
# [right - 2, right), 左闭右开
res[right - 2: right + 1] = '%20'
right -= 3
left -= 1
return ''.join(res)
(版本二)添加空列表,添加匹配的结果
class Solution:
def replaceSpace(self, s: str) -> str:
res = []
for i in range(len(s)):
if s[i] == ' ':
res.append('%20')
else:
res.append(s[i])
return ''.join(res)
(版本三)使用切片
对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值,即同时返回索引以及值:
class Solution:
def replaceSpace(self, s: str) -> str:
n = len(s)
for e, i in enumerate(s[::-1]):
print(i, e)
if i == " ":
s = s[: n - (e + 1)] + "%20" + s[n - e:]
print("")
return s
(版本四)使用join + split
class Solution:
def replaceSpace(self, s: str) -> str:
return "%20".join(s.split(" "))
(版本五)使用replace
class Solution:
def replaceSpace(self, s: str) -> str:
return s.replace(' ', '%20')
反思总结:也可以用双指针法,练习下。
151. 反转字符串中的单词
给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
题目链接:链接
自己理解题目:将字符串以空格分隔,然后转换成列表再reverse,后利用空格拼接成字符串。
class Solution:
def reverseWords(self, s: str) -> str:
s=list(s.split())
s.reverse()
return " ".join(s)
参考答案:
(版本一)先删除空白,然后整个反转,最后单词反转。 因为字符串是不可变类型,所以反转单词的时候,需要将其转换成列表,然后通过join函数再将其转换成列表,所以空间复杂度不是O(1)
class Solution:
def reverseWords(self, s: str) -> str:
# 删除前后空白
s = s.strip()
# 反转整个字符串
s = s[::-1]
# 将字符串拆分为单词,并反转每个单词
s = ' '.join(word[::-1] for word in s.split())
return s
(版本二)使用双指针
class Solution:
def reverseWords(self, s: str) -> str:
# 将字符串拆分为单词,即转换成列表类型
words = s.split()
# 反转单词
left, right = 0, len(words) - 1
while left < right:
words[left], words[right] = words[right], words[left]
left += 1
right -= 1
# 将列表转换成字符串
return " ".join(words)
反思总结:双指针法还是没有领悟到精髓。多练习吧。
剑指 Offer 58 - II. 左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
题目链接:链接
自己理解题目:做切片处理,根据要左旋的个数确定循环几次,然后切片拼接字符串
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
ll=[]
while n>0:
ll.append(s[0])
s=s[1:]
s+=ll.pop()
n-=1
return s
参考答案:
python: (版本一)使用切片
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
return s[n:] + s[:n]
(版本二)使用reversed + join
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:
s_list = list(s)
self.reverse(s_list, 0, n - 1)
self.reverse(s_list, n, len(s_list) - 1)
self.reverse(s_list, 0, len(s_list) - 1)
return ''.join(s_list)
def reverse(self, s, start, end):
while start < end:
s[start], s[end] = s[end], s[start]
start += 1
end -= 1
(版本四)使用 模 +下标
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
new_s = ''
for i in range(len(s)):
j = (i+n)%len(s)
new_s = new_s + s[j]
return new_s
(版本五)使用 模 + 切片
class Solution:
def reverseLeftWords(self, s: str, n: int) -> str:
l = len(s)
# 复制输入字符串与它自己连接
s = s + s
# 计算旋转字符串的起始索引
k = n % (l * 2)
# 从连接的字符串中提取旋转后的字符串并返回
return s[k : k + l]
反思总结:总是借助列表操作字符串,浪费很多空间,这点要改啊~