Article / 文章

LeetCode 第344题:反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

📖 文章摘要

本文详细解析LeetCode第344题“反转字符串”,这是一道简单难度的字符串操作题目。文章提供了双指针和递归两种解法,包含C#、Python、C++三种语言实现,配有详细的算法分析和性能对比。适合初学算法的程序员学习字符串操作。

核心知识点: 双指针、字符串、原地算法
难度等级: 简单
推荐人群: 初学算法的程序员,想要掌握基本字符串操作的开发者

题目描述

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

示例

示例 1:

输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]

示例 2:

输入:s = ["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]

提示

  • 1 <= s.length <= 105
  • s[i] 都是 ASCII 码表中的可打印字符

解题思路

方法一:双指针

使用双指针从两端向中间移动,交换字符。

关键点:

  • 左右指针分别从两端开始
  • 交换两个指针指向的字符
  • 指针向中间移动
  • 当左指针大于等于右指针时停止

具体步骤:

  1. 初始化左指针left = 0,右指针right = length - 1
  2. 当left < right时循环
  3. 交换s[left]和s[right]的值
  4. left++,right–

时间复杂度:O(n) 空间复杂度:O(1)

方法二:递归

使用递归方式从两端向中间交换字符。

关键点:

  • 递归的基本情况是左指针大于等于右指针
  • 每次递归交换两端字符
  • 递归调用处理剩余部分

图解思路

双指针过程分析表

步骤 数组状态 left right 操作
初始 [“h”,“e”,“l”,“l”,“o”] 0 4 交换h和o
第1步 [“o”,“e”,“l”,“l”,“h”] 1 3 交换e和l
第2步 [“o”,“l”,“l”,“e”,“h”] 2 2 结束

递归过程分析

输入:["h","e","l","l","o"]
递归过程:
1. 交换h和o:["o","e","l","l","h"]
2. 递归剩余部分:
   2.1 交换e和l:["o","l","l","e","h"]
   2.2 递归中间的l:不需要交换
结果:["o","l","l","e","h"]

代码实现

C# 实现

public class Solution {
    // 方法一:双指针
    public void ReverseString(char[] s) {
        int left = 0, right = s.Length - 1;
        while (left < right) {
            // 交换字符
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            // 移动指针
            left++;
            right--;
        }
    }
    
    // 方法二:递归
    public void ReverseStringRecursive(char[] s) {
        ReverseStringHelper(s, 0, s.Length - 1);
    }
    
    private void ReverseStringHelper(char[] s, int left, int right) {
        if (left >= right) return;
        
        // 交换字符
        char temp = s[left];
        s[left] = s[right];
        s[right] = temp;
        
        // 递归处理剩余部分
        ReverseStringHelper(s, left + 1, right - 1);
    }
}

Python 实现

class Solution:
    # 方法一:双指针
    def reverseString(self, s: List[str]) -> None:
        left, right = 0, len(s) - 1
        while left < right:
            # Python的优雅交换
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1
    
    # 方法二:递归
    def reverseStringRecursive(self, s: List[str]) -> None:
        def helper(left: int, right: int) -> None:
            if left >= right:
                return
            # 交换字符
            s[left], s[right] = s[right], s[left]
            # 递归处理剩余部分
            helper(left + 1, right - 1)
            
        helper(0, len(s) - 1)

C++ 实现

class Solution {
public:
    // 方法一:双指针
    void reverseString(vector<char>& s) {
        int left = 0, right = s.size() - 1;
        while (left < right) {
            // 交换字符
            swap(s[left], s[right]);
            left++;
            right--;
        }
    }
    
    // 方法二:递归
    void reverseStringRecursive(vector<char>& s) {
        reverseStringHelper(s, 0, s.size() - 1);
    }
    
private:
    void reverseStringHelper(vector<char>& s, int left, int right) {
        if (left >= right) return;
        
        // 交换字符
        swap(s[left], s[right]);
        
        // 递归处理剩余部分
        reverseStringHelper(s, left + 1, right - 1);
    }
};

执行结果

C# 实现

  • 执行用时:248 ms
  • 内存消耗:46.2 MB

Python 实现

  • 执行用时:188 ms
  • 内存消耗:21.3 MB

C++ 实现

  • 执行用时:16 ms
  • 内存消耗:23.1 MB

性能对比

语言 执行用时 内存消耗 特点
C# 248 ms 46.2 MB 代码结构清晰
Python 188 ms 21.3 MB 语法简洁
C++ 16 ms 23.1 MB 性能最优

代码亮点

  1. 🎯 双指针实现简单高效
  2. 💡 递归实现优雅
  3. 🔍 原地修改节省空间
  4. 🎨 代码可读性强

常见错误分析

  1. 🚫 使用额外数组存储
  2. 🚫 指针边界处理错误
  3. 🚫 递归终止条件错误
  4. 🚫 字符交换逻辑错误

解法对比

解法 时间复杂度 空间复杂度 优点 缺点
双指针 O(n) O(1) 简单直观
递归 O(n) O(n) 代码优雅 空间开销大

相关题目


📖 系列导航

🔥 算法专题合集 - 查看完整合集

📢 关注合集更新:点击上方合集链接,关注获取最新题解!目前已更新至第344题。


💬 互动交流

感谢大家耐心阅读到这里!希望这篇题解能够帮助你更好地理解和掌握这道算法题。

如果这篇文章对你有帮助,请:

  • 👍 点个赞,让更多人看到这篇文章
  • 📁 收藏文章,方便后续查阅复习
  • 🔔 关注作者,获取更多高质量算法题解
  • 💭 评论区留言,分享你的解题思路或提出疑问

你的支持是我持续分享的动力!

💡 一起进步:算法学习路上不孤单,欢迎一起交流学习!