2-2 字符串反转(ReversingString)

字符串反转(Reversing a String)

字符串反转是将一个字符串中的字符顺序颠倒的操作。例如将 "hello" 反转后得到 "olleh"

字符串反转有多种实现方式,常见方法包括:

  • 双指针法:使用两个指针分别从字符串的首尾向中间移动,交换字符。
  • 新建字符串法:从原字符串末尾开始,逐个字符拼接到新字符串中。
  • 递归法:利用递归将问题分解为反转子串。
  • 栈方法:利用栈的后进先出(LIFO)特性,将字符依次压栈再弹栈。

双指针法反转字符串

双指针法是最常用的原地(in-place)反转方法,不需要额外空间。

基本思路:

  • 设置左指针 left = 0,右指针 right = len - 1
  • 交换 leftright 位置的字符。
  • 左指针右移,右指针左移,直到两指针相遇或交叉。

"hello" 为例:

初始:   h e l l o
         ^     ^
        left  right

第1步:  o e l l h    交换 h 和 o
          ^ ^
        left right

第2步:  o l l e h    交换 e 和 l
           ^
        left=right  相遇,结束

C++ 实现

#include <iostream>
#include <string>

void reverseString(std::string &s) 
{
    int left = 0;
    int right = s.length() - 1;

    while (left < right) 
    {
        // swap characters
        char temp = s[left];
        s[left] = s[right];
        s[right] = temp;

        left++;
        right--;
    }
}

int main() 
{
    std::string s = "hello";
    std::cout << "Original: " << s << "\n";
    reverseString(s);
    std::cout << "Reversed: " << s << "\n";
    return 0;
}

运行该程序将输出

Original: hello
Reversed: olleh

我们通过 reverseString(s) 对字符串 s 进行原地反转。std::string 以引用方式传递,函数直接修改原字符串。

C 实现

在 C 语言中,字符串以字符数组(char[])表示,以空字符 '\0' 结尾。

#include <stdio.h>
#include <string.h>

void reverseString(char s[]) 
{
    int left = 0;
    int right = strlen(s) - 1;

    while (left < right) 
    {
        // swap characters
        char temp = s[left];
        s[left] = s[right];
        s[right] = temp;

        left++;
        right--;
    }
}

int main() 
{
    char s[] = "hello";
    printf("Original: %s\n", s);
    reverseString(s);
    printf("Reversed: %s\n", s);
    return 0;
}

运行该程序将输出

Original: hello
Reversed: olleh

注意:C 语言中 char s[] = "hello" 会将字符串字面量复制到栈上的数组中,因此可以修改。但如果使用 char *s = "hello",字符串存储在只读段,尝试修改会导致未定义行为。

Python 实现

def reverse_string(s):
    # convert to list since strings are immutable
    chars = list(s)
    left = 0
    right = len(chars) - 1

    while left < right:
        chars[left], chars[right] = chars[right], chars[left]
        left += 1
        right -= 1

    return ''.join(chars)

s = "hello"
print(f"Original: {s}")
print(f"Reversed: {reverse_string(s)}")

运行该程序将输出

Original: hello
Reversed: olleh

Python 中字符串是不可变的(immutable),因此我们先将字符串转为列表,原地交换后再用 ''.join() 拼接回字符串。

Go 实现

Go 中字符串是不可变的字节切片,且使用 UTF-8 编码。为了正确处理 Unicode 字符,我们先将字符串转换为 []rune 切片,再进行原地交换。

package main

import "fmt"

func reverseString(s *string) {
	runes := []rune(*s)
	left := 0
	right := len(runes) - 1

	for left < right {
		runes[left], runes[right] = runes[right], runes[left]
		left++
		right--
	}
	*s = string(runes)
}

func main() {
	s := "hello"
	fmt.Println("Original:", s)
	reverseString(&s)
	fmt.Println("Reversed:", s)
}

运行该程序将输出

Original: hello
Reversed: olleh

Go 通过 []rune 将字符串转换为 Unicode 码点切片,支持多字节字符(如中文)。使用指针 *string 模拟原地修改。runes[left], runes[right] = runes[right], runes[left] 是 Go 的多元赋值,无需临时变量即可完成交换。


新建字符串法反转

新建字符串法从原字符串末尾开始逐个读取字符,拼接到一个新字符串中。这种方法简单直观,但需要 O(n) 的额外空间。

C++ 实现

#include <iostream>
#include <string>

std::string reverseString(const std::string &s) 
{
    std::string result = "";
    for (int i = s.length() - 1; i >= 0; i--) 
    {
        result += s[i];
    }
    return result;
}

int main() 
{
    std::string s = "world";
    std::cout << "Original: " << s << "\n";
    std::cout << "Reversed: " << reverseString(s) << "\n";
    return 0;
}

运行该程序将输出

Original: world
Reversed: dlrow

C 实现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void reverseString(const char src[], char dest[]) 
{
    int len = strlen(src);
    for (int i = 0; i < len; i++) 
    {
        dest[i] = src[len - 1 - i];
    }
    dest[len] = '\0';
}

int main() 
{
    const char *src = "world";
    // allocate destination with same length + null terminator
    char dest[6];
    printf("Original: %s\n", src);
    reverseString(src, dest);
    printf("Reversed: %s\n", dest);
    return 0;
}

运行该程序将输出

Original: world
Reversed: dlrow

Python 实现

def reverse_string(s):
    result = ""
    for i in range(len(s) - 1, -1, -1):
        result += s[i]
    return result

s = "world"
print(f"Original: {s}")
print(f"Reversed: {reverse_string(s)}")

运行该程序将输出

Original: world
Reversed: dlrow

Go 实现

package main

import "fmt"

func reverseString(s string) string {
	runes := []rune(s)
	result := make([]rune, 0, len(runes))
	for i := len(runes) - 1; i >= 0; i-- {
		result = append(result, runes[i])
	}
	return string(result)
}

func main() {
	s := "world"
	fmt.Println("Original:", s)
	fmt.Println("Reversed:", reverseString(s))
}

运行该程序将输出

Original: world
Reversed: dlrow

Go 中先将字符串转为 []rune 以支持 Unicode,然后从末尾向前遍历,将字符逐个追加到新切片中,最后用 string() 转换回字符串。


递归法将字符串反转分解为:先反转除第一个字符外的子串,再将第一个字符放到末尾。

递归的两个要素:

  • 基准情形:当字符串为空或只有一个字符时,直接返回。
  • 递推步骤:反转除首字符外的子串,再将首字符拼接到末尾。

"abc" 为例:

reverse("abc")
= reverse("bc") + 'a'
= (reverse("c") + 'b') + 'a'
= ("c" + 'b') + 'a'
= "cb" + 'a'
= "cba"

C++ 实现

#include <iostream>
#include <string>

std::string reverseString(const std::string &s) 
{
    // base case: empty or single character
    if (s.length() <= 1) 
    {
        return s;
    }
    // recursive step: reverse substring + first char
    return reverseString(s.substr(1)) + s[0];
}

int main() 
{
    std::string s = "abcde";
    std::cout << "Original: " << s << "\n";
    std::cout << "Reversed: " << reverseString(s) << "\n";
    return 0;
}

运行该程序将输出

Original: abcde
Reversed: edcba

C 实现

在 C 中,递归反转通常通过原地交换字符实现,传递左右索引。

#include <stdio.h>
#include <string.h>

void reverseRecursive(char s[], int left, int right) 
{
    // base case: pointers meet or cross
    if (left >= right) 
    {
        return;
    }
    // swap
    char temp = s[left];
    s[left] = s[right];
    s[right] = temp;

    // recursive step
    reverseRecursive(s, left + 1, right - 1);
}

int main() 
{
    char s[] = "abcde";
    printf("Original: %s\n", s);
    reverseRecursive(s, 0, strlen(s) - 1);
    printf("Reversed: %s\n", s);
    return 0;
}

运行该程序将输出

Original: abcde
Reversed: edcba

Python 实现

def reverse_string(s):
    # base case: empty or single character
    if len(s) <= 1:
        return s
    # recursive step
    return reverse_string(s[1:]) + s[0]

s = "abcde"
print(f"Original: {s}")
print(f"Reversed: {reverse_string(s)}")

运行该程序将输出

Original: abcde
Reversed: edcba

Go 实现

package main

import "fmt"

func reverseString(s string) string {
	runes := []rune(s)
	reverseRecursive(runes, 0, len(runes)-1)
	return string(runes)
}

func reverseRecursive(runes []rune, left, right int) {
	// base case: pointers meet or cross
	if left >= right {
		return
	}
	// swap
	runes[left], runes[right] = runes[right], runes[left]
	// recursive step
	reverseRecursive(runes, left+1, right-1)
}

func main() {
	s := "abcde"
	fmt.Println("Original:", s)
	fmt.Println("Reversed:", reverseString(s))
}

运行该程序将输出

Original: abcde
Reversed: edcba

Go 的递归反转采用原地交换方式,通过传递 []rune 切片和左右索引实现。切片在 Go 中是引用类型,对切片元素的修改在函数外可见,因此不需要返回切片。


栈方法反转字符串

利用栈的后进先出(LIFO)特性:先将所有字符依次压入栈,再依次弹出,自然得到反转顺序。

C++ 实现

#include <iostream>
#include <string>
#include <stack>

std::string reverseString(const std::string &s) 
{
    std::stack<char> st;

    // push all characters onto stack
    for (char c : s) 
    {
        st.push(c);
    }

    // pop all characters to build reversed string
    std::string result = "";
    while (!st.empty()) 
    {
        result += st.top();
        st.pop();
    }
    return result;
}

int main() 
{
    std::string s = "hello";
    std::cout << "Original: " << s << "\n";
    std::cout << "Reversed: " << reverseString(s) << "\n";
    return 0;
}

运行该程序将输出

Original: hello
Reversed: olleh

C 实现

C 语言没有内置栈,我们可以用数组和栈顶指针模拟栈。关于栈的数组实现的详细说明,可参考 栈_数组实现

#include <stdio.h>
#include <string.h>

void reverseString(char s[]) 
{
    int len = strlen(s);
    // use array as stack
    char stack[256];
    int top = -1;

    // push all characters onto stack
    for (int i = 0; i < len; i++) 
    {
        stack[++top] = s[i];
    }

    // pop all characters back into string
    for (int i = 0; i < len; i++) 
    {
        s[i] = stack[top--];
    }
}

int main() 
{
    char s[] = "hello";
    printf("Original: %s\n", s);
    reverseString(s);
    printf("Reversed: %s\n", s);
    return 0;
}

运行该程序将输出

Original: hello
Reversed: olleh

Python 实现

def reverse_string(s):
    stack = []

    # push all characters onto stack
    for c in s:
        stack.append(c)

    # pop all characters to build reversed string
    result = ""
    while stack:
        result += stack.pop()
    return result

s = "hello"
print(f"Original: {s}")
print(f"Reversed: {reverse_string(s)}")

运行该程序将输出

Original: hello
Reversed: olleh

Go 实现

Go 没有内置的泛型栈,我们可以使用切片模拟栈的行为。

package main

import "fmt"

func reverseString(s string) string {
	runes := []rune(s)
	stack := make([]rune, 0, len(runes))

	// push all characters onto stack
	for _, r := range runes {
		stack = append(stack, r)
	}

	// pop all characters to build reversed string
	result := make([]rune, 0, len(runes))
	for len(stack) > 0 {
		// pop from top
		top := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		result = append(result, top)
	}
	return string(result)
}

func main() {
	s := "hello"
	fmt.Println("Original:", s)
	fmt.Println("Reversed:", reverseString(s))
}

运行该程序将输出

Original: hello
Reversed: olleh

Go 中使用切片模拟栈:append 相当于压栈,stack[:len(stack)-1] 相当于弹栈。同样先转为 []rune 以确保 Unicode 安全。


各方法对比

方法 时间复杂度 空间复杂度 是否原地 特点
双指针法 O(n) O(1) 最高效,推荐使用
新建字符串法 O(n) O(n) 简单直观,不修改原字符串
递归法 O(n) O(n) C 版本是 优雅但可能栈溢出
栈方法 O(n) O(n) 展示栈的应用,教学价值高

注意:Python 中字符串反转最简洁的写法是切片 s[::-1],以上实现主要是为了演示算法原理。

posted @ 2026-04-16 10:36  游翔  阅读(15)  评论(0)    收藏  举报