Leetcode 344. 反转字符串
讲解前:
这道题一拿到手之后我就先想到的是直接用Python的切片来一行代码搞定,后来发现题目要求对原字符串进行更改,那么原地更改的话就只能对每一个index 的值进行交换了,那么我最先想到的就是双指针的方法
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
# create two pointers
left, right = 0, len(s) - 1
# keep swapping char at left and right index
while left < right:
s[left], s[right] = s[right], s[left]
left = left + 1
right = right - 1
讲解后:
卡哥的思路也是一样的然后呢突然发现自己已经忘记了之前用Java写得时候对于这种交换数值的问题还要先用temp存值的操作,Python确实很方便了相比之下,然后文字版题解中还提到了用for loop的话时间会更短一些因为省去了left right重新赋值还有while loop每次检查条件的过程
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
# create two pointers
left, right = 0, len(s) - 1
# keep swapping char at left and right index
n = len(s)
for i in range(n // 2):
s[i], s[n - i - 1] = s[n - i - 1], s[i]
Leetcode 541. 反转字符串II
讲解前:
这道题我花了比我想象中更多的时间,花了一段时间找到规律在哪里,因为题目中给的两个当我们找到字符串最后的要求让我迷了一会但是后来发现其实就可以按照这个简单的分成两种情况,每一次我们根据left的位置来判断当前字符串中剩余的还没有操作的字符的长度,如果是大于k的,我们就放心的把right 移动到left + k - 1 的位置然后翻转就可以了,不用刻意去保留k - 2k中间的字符,因为我们每次移动left 都是直接往后移动2 * k的位置,然后呢另一种情况就是剩下的长度比k还小,这种情况就直接把right 移动到end of string就可以了
class Solution:
def reverseStr(self, s: str, k: int) -> str:
s = list(s)
# create the left pointer
left = 0
while left < len(s):
cur_length = len(s) - left
# swap k char as long as we have more than k as cur length
if cur_length >= k:
right = left + k - 1
# swap
t_left = left
while t_left < right:
s[t_left], s[right] = s[right], s[t_left]
t_left = t_left + 1
right = right - 1
# we at end of list and only swap the rest of char
else:
right = len(s) - 1
t_left = left
# swap
while t_left < right:
s[t_left], s[right] = s[right], s[t_left]
t_left = t_left + 1
right = right - 1
# update left every loop
left = left + 2 * k
return ''.join(s)
然后这里需要注意的就是当我们在一开始把string转换成list为了更方便swap的时候,在最后返回的时候,不能直接在str(s) 因为这里会单纯的把list的样式完整的变成string包括[] "" 符号,而是需要用空字符的join来完成,同时在我的code里面,我用while loop然后更新left 和 right来进行交换,这里要记得用另一个variable来代替left, 因为left只能在每个循环中increase 2*k,不能在别的地方被更新值
讲解后:
看了文字讲解中的python写法后发现卡哥的这个解法更加简便并且同时也很好理解,这里提醒了一个关于Python语言中切片的优势,在 Python 中,如果切片的结束索引超出了列表的长度,切片操作会自动终止在列表的最后一个索引处,并返回从起始索引到最后一个索引的所有元素。这种行为在 Python 中是很方便的,因为它允许你使用超出列表长度的索引范围而无需担心索引越界的问题。
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):
res[cur: cur + k] = reverse_substring(res[cur: cur + k])
return ''.join(res)
卡码网 54. 替换数字
讲解前:
这里在卡码网上需要用ACM的写法做,所以需要自己用input来接收string,然后呢解法其实并不难,只需要定义一个新的字符串然后遍历input string,如果是字母就正常复制,但是是数字就直接变成'number'就可以了
s = input()
res = ''
for char in s:
if char.isdigit():
res = res + 'number'
else:
res = res + char
print(res)
讲解后:
讲解中提到了另一种解法,可以不需要额外的空间,我大概看懂了,但是有点懒得重新用Python写出来了,文章中只有Cpp的写法
Leetcode 151. 反转字符串中的单词
讲解前:
看到这道题后我脑子里第一个想到的方法就是利用额外的空间先把input里面的所有单词按顺序放进一个list,然后再倒序这个list新建一个新的string就可以了
class Solution:
def reverseWords(self, s: str) -> str:
# get all the word in a list
word_list = s.split()
# use the space to join the list in the reverse order
return " ".join(word_list[::-1])
Python中可以用split直接解决空格的问题然后再用切片来倒序遍历list,再用join来在每个单词中间加上空格,这里我甚至有点觉得有点cheat用Python来这样简单的解决的,我打算还是自己再继续想一想怎么样可以不用extra space来在原地修改字符串解决问题
讲解后:
看了卡哥的讲解以后发现不使用额外空间的解法并没有那么复杂,道理还是很容易理解的,但是代码实现起来其实会需要注意很多细节,我打算自己写一下试一试
好吧我忘记了一个最重要的事情那就是在Python中string本来就是不可变的数据类型,我们没办法在原字符串中直接改变删除空格和反转,所以文字讲解中的Python解法也是用了split() 函数,但是我已经理解了卡哥的翻转字符串然后删除空格再翻转单词的思路了
卡码网 55. 右旋字符串
讲解前:
这道题因为我已经明白Python中字符串不可更改所以我就继续找了个很简单的方法来解决,只需要在原本的字符串后面再跟一遍,然后只返回两个字符串连接部分的就可以了,这样就能类似于向右翻转一样,从字符串的中间开始然后到结尾再从头开始
k = int(input())
s = input()
original_length = len(s)
start_index = original_length - k
s = s + s
for i in range(start_index, start_index + original_length):
print(s[i], end='')
讲解后:
嗷嗷文章中的解法非常巧妙我觉得很有意思,我决定还是用python尝试复刻一遍,非常有意思的思路,
k = int(input())
s = list(input())
s.reverse()
# reverse the k part
left, right = 0, k - 1
while left < right:
s[left], s[right] = s[right], s[left]
left = left + 1
right = right - 1
# reverse the rest of list
left, right = k, len(s) - 1
while left < right:
s[left], s[right] = s[right], s[left]
left = left + 1
right = right - 1
print(''.join(s))