【面试题:字符串反转】字符串反转的艺术:多种实现方式全解析

71 阅读5分钟

字符串反转的艺术:多种实现方式全解析 🌟

在JavaScript编程中,字符串反转是一个经典问题,看似简单却蕴含着丰富的编程智慧。今天,让我们一起探索这个看似基础却充满技巧的操作,看看如何用不同方法优雅地实现字符串反转!✨

一、最简洁的API组合:split + reverse + join

function reverseStr(str) {
    // return str.split('').reverse().join();
    // split() 函数与[...str]作用相同
    return [...str].reverse().join('');
}
console.log(reverseStr('hello')); // 输出: olleh

这是最常用、最简洁的方法。通过[...str]split()函数将字符串转换为字符数组,然后使用数组的reverse()方法反转,最后用join('')拼接成字符串。

优点:代码简洁,可读性强,适合日常开发。
缺点:需要创建中间数组,空间复杂度为O(n)。

相关代码解释:

  1. [...str] 的核心作用是:将字符串 str 拆分为含单个字符的数组,例如:[...'hello'] → 拆分字符串为字符数组 ['h','e','l','l','o']
  2. 调用数组方法 .reverse() → 数组反转为 ['o','l','l','e','h']
  3. 调用 .join('') → 将反转后的数组拼接为字符串 'olleh' 并返回。

二、传统循环法:从后往前拼接

function reverseStr(str) {
    let reversed = '';
    for(let i = str.length - 1; i >= 0; i--) {
        reversed += str[i];
    }
    return reversed;
}
console.log(reverseStr('hello')); // 输出: olleh

这种方法通过从字符串末尾开始遍历,逐步将字符添加到结果字符串中。

优点:无需额外数组,空间复杂度O(1),性能较好。
缺点:代码略显冗长,不如API组合简洁。

相关代码解释:

1、递归核心:拆解 + 拼接

return reverseStr(str.substr(1)) + str.charAt(0);
  • str.substr(1)去掉第一个字符(索引0),返回剩余部分
    例:"hello world".substr(1) → "ello world"
  • str.charAt(0)取第一个字符
    例:"hello world".charAt(0) → "h"
  • reverseStr(str.substr(1))递归反转剩余字符串
    例:反转 "ello world" 得到 "dlrow olle"
  • 最后拼接:反转后的字符串 + 第一个字符
    例:"dlrow olle" + "h" → "dlrow olleh"

2、substr函数

substr 是一个用于截取字符串子串的函数:

  • 语法str.substr(start, length)

  • 作用:从 start 位置开始,截取 length 个字符

  • 特点

    • start 可为负数(表示从末尾开始)
    • length 可省略(默认截取到字符串结尾)

✅ 示例:

"hello".substr(1, 3) // → "ell"
"hello".substr(-2)   // → "lo"

三、递归方法:函数自己调用自己 🔄

function reverseStr(str) {
    if(str === "") {
        // 递归停止的开关
        return "";
    } else {
        return reverseStr(str.substr(1)) + str.charAt(0);
    }
}
console.log(reverseStr("hello world")); // 输出: dlrow olleh

递归法将问题拆解为"剩余字符串的反转 + 首字符",通过递归逐步缩小问题规模。

优点:代码简洁,体现了递归思维。
缺点:有爆栈风险(长字符串可能导致栈溢出),内存开销较大。

四、for...of循环法:优雅的遍历

function reverseStr(str) {
    let reversed = ''; // 初始化空字符串
    for(const char of str) { // 遍历字符串的每个字符
        reversed = char + reversed; // 当前字符 + 已反转部分
    }
    return reversed;
}
console.log(reverseStr("hello world")); // 输出: dlrow olleh

具体执行过程

步骤charreversed (当前结果)操作
1'h''''h' + '' → 'h'
2'e''h''e' + 'h' → 'eh'
3'l''eh''l' + 'eh' → 'leh'
4'l''leh''l' + 'leh' → 'lleh'
5'o''lleh''o' + 'lleh' → 'olleh'
6' ''olleh'' ' + 'olleh' → ' olleh'
7'w'' olleh''w' + ' olleh' → 'w olleh'
8'o''w olleh''o' + 'w olleh' → 'ow olleh'
9'r''ow olleh''r' + 'ow olleh' → 'row olleh'
10'l''row olleh''l' + 'row olleh' → 'lrow olleh'
11'd''lrow olleh''d' + 'lrow olleh' → 'dlrow olleh'

这种方法利用ES6的for...of循环,从前往后遍历字符串,但将每个字符加到结果字符串的前面。

优点:代码简洁易读,语义清晰。
缺点:与传统循环法类似,需要创建新字符串。

五、reduce方法:函数式编程的优雅

function reverseStr(str) {
    return [...str].reduce((reversed, char) => char + reversed, '');
}
console.log(reverseStr("hello world")); // 输出: dlrow olleh

利用reduce函数,将字符串字符数组转换为反转后的字符串。

优点:函数式编程风格,代码简洁。
缺点:与split + reverse + join相比,性能可能稍逊。

相关代码解释

1、 .reduce(...):数组的"聚合器"

array.reduce(callback, initialValue)
  • 作用:将数组元素逐步"聚合"成一个值
  • 关键点reduce会按顺序处理数组元素

2、 (reversed, char) => char + reversed:核心回调函数

  • reversed:累积结果(之前反转的部分)
  • char:当前处理的字符
  • char + reversed把当前字符放在已反转字符串的前面

💡 关键技巧char + reversed(不是reversed + char!)
这才是实现反转的关键!

面试官的内心:你为什么需要知道这些方法?

面试官问字符串反转,绝不仅仅是为了得到一个正确答案,而是想考察:

  • API的熟练度:是否熟悉字符串和数组的常用方法
  • 代码的逻辑能力:能否清晰表达问题的解决思路
  • 解题的多样性:能否提供多种解决方案并理解其差异
  • 对性能的考量:是否了解不同方法的时间/空间复杂度

总结与建议

方法代码简洁度空间复杂度适合场景
split+reverse+join⭐⭐⭐⭐⭐O(n)日常开发,简单易懂
for循环⭐⭐⭐O(1)大字符串处理,性能敏感
递归⭐⭐⭐⭐O(n)理解递归思维,不适用于长字符串
for...of⭐⭐⭐⭐O(n)ES6新特性,代码清晰
reduce⭐⭐⭐⭐O(n)函数式编程风格

在日常开发中,split + reverse + join组合是最常用且最推荐的方法。但在处理超长字符串时,循环法可能更高效。

记住,编程不是寻找唯一答案,而是找到最适合当前场景的解决方案。掌握多种方法,才能在不同情况下游刃有余!💪