字符串反转是一个经典的编程面试题,看似简单,却能有效考察候选人的多个方面:
- API 熟练度:对 JavaScript 内置方法的掌握程度
- 代码逻辑能力:能否想出多种解法
- 算法思维:是否理解递归等高级概念
本文将详细介绍 6 种实现字符串反转的方法,从最简洁到最优雅,帮助你全面掌握这道经典面试题。
方法一:ES6 扩展运算符 + reverse() + join()
javascript
function reverseStr(str) {
return [...str].reverse().join('');
}
console.log(reverseStr('abc')); // 输出: 'cba'
解析:
[...str]:使用 ES6 扩展运算符将字符串转换为字符数组.reverse():调用数组的 reverse() 方法反转数组.join(''):将数组拼接回字符串
优点 :代码简洁优雅,可读性强
时间复杂度 :O(n)
空间复杂度:O(n)
方法二:传统 split() 方法
javascript
function reverseStr(str) {
return str.split('').reverse().join('');
}
解析:
split(''):传统方法,将字符串按空字符切割成字符数组- 后续步骤同方法一
特点:这是最经典的实现方式,与方法一本质相同,只是字符串转数组的方式不同。
方法三:for 循环倒序遍历
javascript
function reverseStr(str) {
let reversed = '';
for (let i = str.length - 1; i >= 0; i--) {
reversed += str[i];
}
return reversed;
}
console.log(reverseStr('abc')); // 输出: 'cba'
解析:
- 从字符串末尾开始向前遍历
- 逐个字符拼接到新字符串
优点 :逻辑清晰,不依赖高阶 API
缺点 :字符串拼接在循环中效率较低(每次拼接都会创建新字符串)
时间复杂度:O(n²)(理论上,但现代 JS 引擎有优化)
方法四:for...of 循环正序遍历
javascript
function reverseStr(str) {
let reversed = '';
for (let char of str) {
reversed = char + reversed;
}
return reversed;
}
console.log(reverseStr('hello')); // 输出: 'olleh'
解析:
- 使用 ES6 的
for...of循环正序遍历字符串 - 关键技巧 :每次将新字符添加到结果字符串的前面 (
char + reversed)
优点 :代码简洁,易于理解
特点:通过改变拼接顺序实现反转,思路巧妙
方法五:递归实现
javascript
function reverseStr(str) {
// 递归退出条件
if (str === '') {
return '';
} else {
// 递归:反转剩余字符串 + 第一个字符
return reverseStr(str.substr(1)) + str.charAt(0);
}
}
console.log(reverseStr('hello')); // 输出: 'olleh'
解析:
核心思想:将大问题分解为小问题
- 递归逻辑 :reverseStr('hello') = reverseStr('ello') +
'h' - 退出条件:当字符串为空时返回空字符串
执行过程(以 'abc' 为例):
bash
reverseStr('abc')
→ reverseStr('bc') + 'a'
→ reverseStr('c') + 'b' + 'a'
→ reverseStr('') + 'c' + 'b' + 'a'
→ '' + 'c' + 'b' + 'a'
→ 'cba'
优点 :展示函数式编程思维,面试加分项
缺点 :可能导致栈溢出(字符串过长时)
时间复杂度:O(n²)(substr 每次创建新字符串)
方法六:reduce() 函数式编程
javascript
function reverseStr(str) {
return [...str].reduce((reversed, char) => char + reversed, '');
}
console.log(reverseStr('hello')); // 输出: 'olleh'
解析:
reduce() 是数组的高阶函数,用于将数组"归约"为单一值:
acc(accumulator) :累积结果,初始值为''char(current) :当前字符- 归约逻辑 :
char + reversed将当前字符添加到结果前面
执行过程:
javascript
const arr = ['h', 'e', 'l', 'l', 'o'];
reduce 过程:
'' + 'h' → 'h'
'h' + 'e' → 'eh'
'eh' + 'l' → 'leh'
'leh' + 'l' → 'lleh'
'lleh' + 'o' → 'olleh'
优点:
- 函数式编程风格
- 代码简洁且优雅
- 展示对高阶函数的深刻理解
时间复杂度 :O(n)
空间复杂度:O(n)
🚀扩展知识:reduce 函数详解
由于 reduce 方法较为抽象,这里单独说明:
javascript
const arr = [1, 2, 3, 4, 5, 6];
const total = arr.reduce((acc, cur) => {
console.log(acc, cur);
return acc + cur;
}, 0); // 初始值
console.log(total); // 21
执行过程:
yaml
acc: 0, cur: 1 → 返回 1
acc: 1, cur: 2 → 返回 3
acc: 3, cur: 3 → 返回 6
acc: 6, cur: 4 → 返回 10
acc: 10, cur: 5 → 返回 15
acc: 15, cur: 6 → 返回 21
核心概念:
- acc:累加器,存储上一次的计算结果
- cur:当前遍历到的数组元素
- 初始值:第一次调用时 acc 的值
性能对比
| 方法 | 代码量 | 可读性 | 性能 | 推荐指数 |
|---|---|---|---|---|
| 扩展运算符 + reverse | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| for 循环倒序 | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ |
| for...of 正序 | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 递归 | ⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ |
| reduce | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
面试建议
第一步:快速给出基础解法
先写出方法一(扩展运算符 + reverse),展示你对 JavaScript API 的熟练掌握。
javascript
function reverseStr(str) {
return [...str].reverse().join('');
}
第二步:展示多种思路
主动询问面试官:"我还可以用其他方法实现,比如循环、递归或 reduce,您想看哪种?"
第三步:深入讨论
- 性能分析:讨论各方法的时间/空间复杂度
- 边界情况:空字符串、特殊字符、Unicode 字符
- 实际应用:什么场景下选择什么方法
总结
字符串反转虽然简单,但包含了多种编程范式:
- 命令式编程:for 循环
- 函数式编程:reduce、递归
- 现代 JavaScript:扩展运算符、for...of
掌握这些方法不仅能应对面试,更能提升你的编程思维和代码能力。在实际开发中,推荐使用方法一 (扩展运算符)或方法六(reduce),它们简洁、高效且易于维护。
记住:面试不仅是解决问题,更是展示你的思考过程和代码素养。多种解法的掌握会让你在众多候选人中脱颖而出!
欢迎各位大佬在评论区分享其他解法