344.反转字符串(易)
非常像206反转列表,当时是用的双指针方法,需要得知前一个pre的位置和当前的cur进行调换
字符串也是一种数组,所以元素在内存中是连续分布,这就决定了反转链表和反转字符串方式上还是有所差异的。
思路:对于字符串,我们定义最前和最后两个指针,交换位置再向中间移动
- 时间复杂度: O(n)
- 空间复杂度: O(1)
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
双指针方法
"""
i = 0
j = len(s) -1
while i<j:
swap = s[i]
s[i] = s[j]
s[j] = swap
i+=1
j-=1
一些补充的非常高效的方式:
# 使用库函数reversed
s[:] = reversed(s)
# 使用reverse()
s.reverse()
# 使用切片
s[:] = s[::-1]
# 使用列表推导
# 从len(s)-1最后一位开始,到0(左闭右开),以-1移动
s[:] = [s[i] for i in range(len(s)-1, -1, -1)]
# 使用栈
stack = []
for char in s:
stack.append[char]
for i in range(len(s)):
s[i] = stack.pop()
541. 反转字符串II
在自己尝试编写这道题时犯了3个错误:
(1)交换的方式错误-思考错;
(2)list和str转换错误:reverse_str
方法试图将列表转换回字符串,但使用了 str(s1)
,这实际上会生成类似于 "['a', 'b', 'c']" 的字符串,而不是你想要的 "abc"。正确的做法是使用 ''.join(s1)
将字符列表连接成字符串。
(3)字符串连接更新处理有误:python中字符串的内容不可以像list一样逐位变化所以要按位处理先转为list,最后再用’’.join(s)的形式转为字符串
(4)本题理解题意之后是发现对[0,2k),[2k, 4k)…这样做前k个的字符反转,如果用while计数过于麻烦了,所以用for循环,for i in range(0, len(s), 2k)以步长2k移动
(5)补充一点知识:
在Python中,[:]
和 [::]
都是切片操作符的用法,用于操作列表(以及其他序列类型如字符串和元组)的子集,但它们有细微的差别:
[:]
- 复制整个序列: 用于创建序列的一个浅拷贝。
[::]
- 带步长的切片操作:长定义了在遍历序列时每次跳过的元素数量。如果步长省略(如在 [::]
中),它默认为 1
,这意味着每个元素都被包括,所以在这种情况下,[::]
的效果与 [:]
相同。长定义了在遍历序列时每次跳过的元素数量。如果步长省略(如在 [::]
中),它默认为 1
,这意味着每个元素都被包括,所以在这种情况下,[::]
的效果与 [:]
相同。 例如:
lst = [1, 2, 3, 4, 5]
# 创建lst的一个完整副本
copy_lst = lst[:]
# 创建lst的一个完整副本,步长为1
copy_lst_with_step = lst[::]
# 每隔一个元素取值,步长为2
every_second_element = lst[::2]
本题代码:
class Solution:
def reverseStr(self, s: str, k: int) -> str:
if len(s) <k:
return self.reverse_str(list(s))
if k < len(s) <2*k:
return self.reverse_str(list(s[0:k]))+s[k:]
s = list(s) # 注意python中字符串的内容不可以像list一样逐位变化
for start in range(0, len(s), 2*k): # 重要!当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章
s[start:start+k] = self.reverse_str(list(s[start:start+k])) # 和上一题是一样的
return ''.join(s) #注意列表转字符串的方式!!
def reverse_str(self, s1: list)->str:
i = 0
j = len(s1) -1
while i <j:
swap = s1[i]
s1[i] = s1[j]
s1[j] = swap
i+=1
j-=1
return ''.join(s1)
卡码网:54.替换数字
思路重点:(1)双指针思想:i指向新长度的末尾,j指向旧长度的末尾(2)从后向前填充而不是从前向后填充:从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素整体向后移动;很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
string = input()
s = list(string)
for i in range(len(s)):
if ord('9')>=ord(s[i])>=ord('0'):
s[i] = 'number'
print(''.join(s))
151.翻转字符串里的单词
如果直接用split然后倒叙输入,这道题就失去意义了
想一下,我们将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,单词不就正过来了。
所以解题思路如下:
- 移除多余空格
- 将整个字符串反转
- 将每个单词反转
举个例子,源字符串为:"the sky is blue "
- 移除多余空格 : "the sky is blue"
- 字符串反转:"eulb si yks eht"
- 单词反转:"blue is sky the"
1、双指针移除空格:
类似之前数组中的移除元素的题,快指针fast获取题目要求的字母,慢指针指向要替换的位置
# 伪代码
void removeExtraSpaces(string& s) {//去除所有空格并在相邻单词之间添加空格, 快慢指针。
int slow = 0; //整体思想参考https://programmercarl.com/0027.移除元素.html
for (int i = 0; i < s.size(); ++i) { //
if (s[i] != ' ') { //遇到非空格就处理,即删除所有空格。
if (slow != 0) s[slow++] = ' '; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。
while (i < s.size() && s[i] != ' ') { //补上该单词,遇到空格说明单词结束。
s[slow++] = s[i++];
}
}
}
s.resize(slow); //slow的大小即为去除多余空格后的大小。
}
**2、python代码:**这里好像没有用到刚刚移除空格的思路
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
感觉应该把c++的双指针移除空格的方式写一遍
卡码网:55.右旋转字符串
**思路:**通过 整体倒叙,把两段子串顺序颠倒,两个段子串里的的字符在倒叙一把,负负得正,这样就不影响子串里面字符的顺序了。
#获取输入的数字k和字符串
k = int(input())
s = input()
#通过切片反转第一段和第二段字符串
#注意:python中字符串是不可变的,所以也需要额外空间
s = s[len(s)-k:] + s[:len(s)-k]
print(s)