代码随想录算法训练营Day8 | 字符串 Part 1

一、今日学习目标

  1. 掌握字符串反转的核心思路,能够用双指针法实现基础字符串反转(LeetCode 344 题)

  2. 理解分段反转逻辑,解决 "每 2k 个字符反转前 k 个" 的进阶问题(LeetCode 541 题)

  3. 学会字符替换技巧,完成数字字符到特定字符串的替换(卡码网 54 题)

  4. 明确库函数的适用场景,在 "手动实现" 与 "高效调用" 之间建立平衡

二、核心知识梳理

1. 字符串的本质特性

  • 在 Python 中,字符串是不可变序列,修改字符串需先转换为列表(如list(s)),操作后再转回字符串(''.join(list)

  • 反转操作的核心是元素交换,双指针法是实现反转的高效方式(时间复杂度 O (n),空间复杂度 O (1),原地修改场景)

2. 双指针法原理

  • 定义左指针left(起始索引 0)和右指针right(起始索引len(s)-1

  • 交换leftright指向的元素,然后left右移、right左移,直到left >= right

3. 分段反转逻辑(541 题核心)

  • 遍历字符串时,以2k为步长划分区间

  • 对每个区间:若长度 >=k,则反转前 k 个字符;若长度 < k,则反转全部剩余字符

  • 关键:计算每个分段的反转边界(startmin(start+k-1, len(s)-1)

4. 字符替换技巧

  • 对于需替换字符的场景(如数字→"number"),推荐用列表构建结果(避免字符串拼接的 O (n²) 时间复杂度)

  • 遍历原字符串,遇到目标字符则追加替换内容,否则直接追加原字符

三、实战解题

1、反转字符串

题目描述

LeetCode 344. 反转字符串

文章讲解

文章链接

Python代码
class Solution(object):
    def reverseString(self, s):
        """
        :type s: List[str]
        :rtype: None Do not return anything, modify s in-place instead.
        """
        i, j = 0, len(s)-1
        while i < j:
            s[i], s[j] = s[j], s[i]
            i += 1
            j -= 1
        return s
调试过程

通过双指针从两端向中间逼近,每步交换一对字符,实现原地反转,无需额外空间。

2、反转字符串②

题目描述

LeetCode 541 反转字符串②

文章讲解

文章链接

Python代码
 
class Solution(object):
    def reverseStr(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: str
        """
        i = 0
        chars = list(s)

        while i < len(chars):
            chars[i:i+k] = chars[i:i+k][::-1]
            i += 2*k
        
        return ''.join(chars)
调试过程

2k为步长遍历,每次确定当前分段的反转范围[start, end],用双指针完成局部反转,兼顾不同长度的剩余字符场景。

3、替换数字

题目描述

卡码网:54.替换数字

文章讲解

文章链接

Python代码
class Solution(object):
    def subsitute_numbers(self, s):
        """
        :type s: str
        :rtype: str
        """
        
        count = sum(1 for char in s if char.isdigit())
        expand_len = len(s) + (count * 5) 
        res = [''] * expand_len
        
        new_index = expand_len - 1 
        old_index = len(s) - 1 
        
        while old_index >= 0: 
            if s[old_index].isdigit():
                res[new_index-5:new_index+1] = "number"
                new_index -= 6
            else:
                res[new_index] = s[old_index]
                new_index -= 1
            old_index -= 1
        
        return "".join(res)
        
if __name__ == "__main__":
    solution = Solution()

    while True:
        try:
            s = input()
            result = solution.subsitute_numbers(s)
            print(result)
        except EOFError:
            break
调试过程

用列表res收集结果,遍历字符串时判断字符是否为数字,按需追加 "number" 或原字符,最后通过join高效拼接(时间复杂度 O (n))。

四、易错点总结

  1. 索引越界问题:在 541 题中,计算end时需用min(start + k - 1, n-1),避免因剩余字符不足 k 导致的索引超出范围。

  2. 字符串不可变性误区:Python 中直接修改字符串元素(如s[0] = 'a')会报错,需先转为列表处理。

  3. 步长计算错误:541 题的遍历步长是2*k,而非k,否则会重复处理已反转的区间。

  4. 替换效率问题:若用字符串直接拼接(如res += "number"),每次操作会创建新字符串,时间复杂度升至 O (n²),推荐用列表。

  5. 边界条件遗漏:处理空字符串(如 344 题输入为空列表)时,双指针循环不会执行,需确保代码无异常。

五、扩展思考

  1. 库函数的合理使用:Python 的s[::-1]可一键反转字符串,但 344 题要求原地修改,此时需手动实现;实际开发中,若无需原地修改,库函数是更高效的选择。

  2. 反转的其他实现方式:递归法(空间复杂度 O (n),递归栈开销)、切片法(s_list[start:end+1] = s_list[start:end+1][::-1]),但双指针法仍是最优解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山数转码ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值