2024/12/12 【字符串】LeetCode541. 反转字符串 II 【√】知识点:字符串是不可变类型,及其与切片的关系,理解[ : : -1]

541. 反转字符串 II - 力扣(LeetCode)

代码随想录

题意理解需要花点时间,与昨天的344. 反转字符串 - 力扣(LeetCode)不同在于,昨天题目的字符串是字符列表类型,今天的字符串是双括号括起来的str类型。

这样造成了一些处理上的不同:需要考虑到str类型是不可变类型,对其进行处理,需要转为list类型,返回结果的时候,需要再把字符的list列表,通过‘’.join(list_name)方法把字符拼接成字符串。

我的解答:

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        n = len(s)
        rem = n % 2*k
        cycles = n // 2*k
        s = list(s)
        #循环处理每个2k范围内的前k个字符
        for i in range(cycles):
            s[i*2*k : i*2*k+k] = reversed(s[i*2*k : i*2*k+k])

        #处理剩余的不足以构成一个2k范围区间的字符
        if rem < 2*k and rem >= k:
            s[cycles*2*k : cycles*2*k+k] = reversed(s[cycles*2*k : cycles*2*k+k])
        elif rem < k:
            s[cycles*2*k : cycles*2*k+k] = reversed(s[cycles*2*k : cycles*2*k+k])
        s = ''.join(s)
        return s  

代码随想录提供的代码:

版本1:同样的思路,但是灵活应用range(start,end,step)更加简洁

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        n = len(s)
        res = list(s)
        for cur in range(0, n, 2*k):
            res[cur:cur+k] = res[cur:cur+k][::-1] 
        return ''.join(res)

版本2:

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        p = 0
        while p < len(s):
            p2 = p + k
            s = s[:p] + s[p:p2][::-1] + s[p2:]
            p += 2*k
        return s

1.

s = list(s)

的必要性:

字符串是不可变类型(immutable)。这意味着不能直接修改字符串中的某个字符或者通过切片来替换它。

错误代码:

s[:k] = reversed(s)

错误分析:

代码中的 s[:k] = reversed(s) 试图将字符串 s 中的前 k 个字符替换为字符串 s 的反转(reversed(s) 返回的是一个反转的可迭代对象)。但是,字符串不能像列表一样直接进行切片赋值,因此会抛出这个错误。

示例:

s = "hello"
s[:3] = "abc"  # 会报错,因为字符串是不可变的

正确的做法:

如果你希望对字符串的某一部分进行替换,可以先将字符串转换为列表(列表是可变的),然后进行操作。完成操作后,再将列表转换回字符串。

修改方法:

s = "hello"
k = 3
# 先将字符串转为列表
s_list = list(s)

# 反转字符串后取前k个字符
s_list[:k] = list(reversed(s))

# 将列表再转回字符串
s = ''.join(s_list)

print(s)

在这段代码中:

  • list(s) 将字符串转换为一个列表。
  • reversed(s) 返回一个反转的可迭代对象,所以通过 list(reversed(s)) 可以获得一个反转后的列表。
  • 最后,使用 ''.join(s_list) 将列表重新组合成一个字符串。

2.

''.join(s_list)

''.join(s_list) 是一个用于将列表 s_list 中的元素合并成一个字符串的方法。它的作用是连接列表中的所有字符串元素,生成一个新的单一字符串。

详细解释:

  • ''.join(iterable):这是 str 类型的一个方法,用于将一个可迭代对象(如列表、元组等)中的所有元素连接成一个新的字符串。连接时,可以指定一个分隔符(通过 ''),即在每个元素之间插入的字符串。

    • iterable:可以是任何可迭代对象(如列表、元组、字符串等)。在此情况下,它是一个字符串列表 s_list
    • '':表示连接时没有任何分隔符。也就是说,所有元素将被直接连接起来。

示例:拼接字符串的效率对比

# 使用 '+' 拼接字符串
result = ""
for word in ['H', 'e', 'l', 'l', 'o']:
    result += word  # 每次拼接都会创建一个新的字符串

print(result)  # 输出:Hello

# 使用 ''.join 拼接字符串
result = ''.join(['H', 'e', 'l', 'l', 'o'])  # 只会创建一个新字符串
print(result)  # 输出:Hello

使用 join 方法在多个字符串拼接时效率较高,因为它会在一个操作中完成所有的拼接,而使用 + 会创建多个临时字符串,导致更多的内存开销。

总结来说,''.join(s_list) 是一个高效且常用的将列表中的元素合并为字符串的方法,特别适用于字符串拼接和字符串重组操作。

3. 理解s[p: p2][::-1] 

s[p: p2][::-1] 是 Python 中常见的切片操作反向切片的组合。


分解解释

  1. s[p: p2]

    • 这里对字符串 s 进行切片操作。
    • p 是起始索引,p2 是结束索引(不包括 p2 处的字符)。
    • 它会返回一个从索引 pp2-1 的子字符串。
  2. [::-1]

    • 这是反向切片操作,用于将字符串或列表反转
    • 其中 : 表示取整个字符串(或列表),-1 表示步长为 -1,意味着从末尾向前进行切片。

    示例

    s = "abcdefg"
    print(s[::-1])  # 输出:'gfedcba',将整个字符串反转
  3. 组合 s[p: p2][::-1]

    • s[p: p2] 先提取字符串的子串。
    • [:: -1] 再将这个子串反转。

    示例

    s = "abcdefg"
    p = 1
    p2 = 5
    result = s[p: p2][::-1]
    print(result)  # 输出:'edcb'

总结

  • s[p: p2] 提取字符串 s 的一部分(从索引 pp2-1)。
  • [:: -1] 将提取的部分反转。
  • 整个表达式 s[p: p2][::-1] 就是提取一个子串并反转

这个组合操作在需要对字符串的某一部分进行反向处理时非常常用。

4. 字符串是不可变类型,及其与切片的关系

字符串之所以被设计成不可变类型(immutable),是出于以下几个原因:


(1). 内存管理和性能优化

  • 不可变对象 可以被多个引用共享,避免重复创建,节省内存。
  • 在 Python 中,字符串常被用作键(比如字典中的键),不可变性使字符串具有哈希值,从而可以快速检索和比较。

示例

a = "hello"
b = "hello"
print(id(a), id(b))  # 输出相同的内存地址,表明 a 和 b 指向同一个对象
  • 字符串是不可变的,因此 "hello" 不会因为某个变量的操作而被修改,多个引用也无需担心意外变化。

(2). 保证数据安全

  • 由于不可变,字符串在多线程或共享资源的环境中更安全,不会因为某个操作导致意外修改。

(3). 字符串的操作返回新对象,而非修改原对象

  • 任何对字符串进行“修改”的操作(比如拼接、切片等)都会返回一个新字符串对象,而原字符串保持不变。

示例:

s = "hello"
s_new = s + " world"
print(s)      # 输出:hello
print(s_new)  # 输出:hello world
  • 原字符串 s 没有改变,操作后的结果存储在新的变量 s_new 中。

(4). 切片操作和不可变性的关系

当你对字符串进行切片操作时,实际上 不会修改原字符串,而是创建了一个新字符串对象,并返回这个新对象。

示例

s = "abcdef"
s2 = s[1:4]   # 切片操作,提取索引 1 到 3 的子串
print(s2)     # 输出:'bcd'
print(s)      # 原字符串 'abcdef' 没有变化
  • s[1:4] 返回一个新的字符串 'bcd',而 s 依旧是 'abcdef'
  • 原因是字符串是不可变的,Python 不会修改 原字符串,而是生成一个新的字符串对象。

总结

  • 字符串是不可变类型,意味着字符串对象一旦创建,其内容无法被修改。
  • 但这并不意味着不能进行操作。对字符串的任何“修改”操作(例如切片、拼接、替换等)都会返回一个新对象,而不会改变原字符串本身。
  • 切片操作之所以能执行,是因为它只是提取出部分内容,并返回一个新的字符串对象。

 

posted @ 2024-12-17 10:16  axuu  阅读(9)  评论(0编辑  收藏  举报