提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
leetcode.186.反转字符串中的单词
https://leetcode.cn/problems/reverse-words-in-a-string-ii/
给你一个字符数组 s ,反转其中 单词 的顺序。
单词 的定义为:单词是一个由非空格字符组成的序列。s 中的单词将会由单个空格分隔。
必须设计并实现 原地 解法来解决此问题,即不分配额外的空间。
示例 1:
输入:s = [“t”,“h”,“e”," “,“s”,“k”,“y”,” “,“i”,“s”,” “,“b”,“l”,“u”,“e”]
输出:[“b”,“l”,“u”,“e”,” “,“i”,“s”,” “,“s”,“k”,“y”,” ",“t”,“h”,“e”]
思路:
先把全体字符全部反转,然后找到每个空格之间的单词,反转每个单词
class Solution:
def reverseWords(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
def reverse(s_list):
if len(s_list)==1:
return s_list
left = 0
right = len(s_list)-1
while left < right:
s_list[left], s_list[right] = s_list[right], s_list[left]
left += 1
right -= 1
return s_list
reverse(s)
if len(s) == 1:
return s
ex_left = 0
ex_right = 1
while ex_right<len(s):
if s[ex_right] != " " :
ex_right += 1
else:
s[ex_left:ex_right] = reverse(s[ex_left:ex_right])
ex_left = ex_right + 1
ex_right += 1
s[ex_left:ex_right] = reverse(s[ex_left:ex_right])
在Python中,字符串是不可变(immutable)的,这意味着一旦一个字符串被创建,你不能改变这个字符串的内容。但是,列表(list)是可变的(mutable),这意味着你可以改变列表中的元素。
在你提供的代码中,你正在处理一个字符串列表 s
。下面是关于你的代码的一些解释,以及何时列表的原始值会被修改,何时不会:
- 函数
reverse(s_list)
:- 这个函数接收一个列表
s_list
,并在原地(in-place)反转这个列表。这意味着s_list
的原始值会被修改,因为列表是可变的。
- 这个函数接收一个列表
- 调用
reverse(s)
:- 当你调用
reverse(s)
时,列表s
的内容会被反转。由于reverse
函数是原地修改列表,所以s
的原始值会被改变。
- 当你调用
- 切片赋值:
- 表达式
s[ex_left:ex_right] = reverse(s[ex_left:ex_right])
是将s
列表中的一个切片替换为另一个反转后的切片。这同样会修改原始列表s
。
总的来说,由于列表是可变的,任何对列表的修改(如元素赋值、切片赋值、方法调用如list.append()
或list.extend()
等)都会改变原始列表。
需要注意的是,虽然列表本身是可变的,但如果你在列表中存储的是字符串,那么这些字符串本身是不可变的。例如,如果你尝试s[0][0] = 'a'
,这将会引发错误,因为你不能修改字符串的某个字符。但你可以通过赋值来替换整个字符串,例如s[0] = 'another_string'
,这将修改列表s
的第一个元素。
最后,代码中的注释# Do not return anything, modify s in-place instead.
表明这个函数的目的是修改传入的列表s
,而不是返回一个新的列表。根据你的代码逻辑,原始的列表s
会被就地修改。
- 表达式
第26行修改成这样就会失败:
reverse(s[ex_left:ex_right])
这是为什么?
当你调用 reverse(s[ex_left:ex_right])
而不是使用切片赋值,你确实调用了 reverse
函数,该函数会原地修改传入的列表。然而,s[ex_left:ex_right]
是一个列表的切片,它创建了一个新的列表(这个新列表是原始列表 s
的一个子集的浅拷贝),然后你将这个新列表传递给了 reverse
函数。
以下是为什么这样做不会修改原始列表 s
的原因:
- 列表的切片操作返回一个新的列表,即使原始列表是可变的。
- 当你将这个切片传递给
reverse
函数时,实际上你是在反转这个新列表,而不是原始列表s
。 - 由于新列表与原始列表
s
是独立的,所以对新列表的修改不会影响原始列表。
为了修改原始列表s
,你需要使用切片赋值,像这样:
s[ex_left:ex_right] = reverse(s[ex_left:ex_right])
这个表达式将反转后的新列表(reverse(s[ex_left:ex_right])
的结果)赋值给原始列表 s
的相应切片位置,从而修改了原始列表 s
。
所以,为了达到你的目的,你应该保留原来的切片赋值方式,而不是仅仅调用 reverse(s[ex_left:ex_right])
。