面试常客:字符串算法从入门到进阶

最近在整理算法笔记时,发现字符串相关的面试题真是常青树。今天就借着我的学习笔记,和大家聊聊字符串算法中的几个经典问题,以及JS中一些容易被忽略的底层细节。


一、反转字符串,你真的会了吗?

先来个开胃菜------反转字符串。别看它简单,里面藏着不少JS的"坑"和设计哲学。

最直接的解法

javascript

ini 复制代码
const str = 'abc';
const res = str.split('').reverse().join('');
console.log(res); // 'cba'

核心思路就三步:

  1. split('') ------ 把字符串拆成字符数组
  2. reverse() ------ 反转数组
  3. join('') ------ 把数组拼回字符串

为什么不能直接在字符串上调用 reverse()?

因为字符串是简单数据类型 (基本类型),而 reverse() 是数组原型上的方法。JS 的字符串并没有提供 reverse API,但数组有。

包装类的"魔法"

你可能好奇过:既然 str 是简单数据类型,为什么 str.length 能用?

javascript

ini 复制代码
const str = 'abc';
console.log(str.length); // 3

这背后其实是 JS 的包装类 在悄悄工作。当我们试图访问基本类型的属性时,JS 底层会临时用 new String(str) 把它包装成一个 String 对象实例,调用完属性/方法后,再把它"打回原形"变回简单数据类型。

就像灰姑娘的魔法,到了点就恢复原样 ✨

javascript

javascript 复制代码
const str2 = new String("abc"); // 这才是真正的字符串对象
console.log(str2.length); // 3
console.log(Object.prototype.toString.call(str2)); // "[object String]"

二、一切皆对象,Object.prototype.toString 的妙用

在学习过程中,有一个知识点让我豁然开朗 ------ Object.prototype.toString 的作用。

javascript

css 复制代码
let o = { a: 1, b: 2 };
o.toString(); // "[object Object]"
JSON.stringify(o); // '{"a":1,"b":2}'

toString() 的职责是把对象序列化(字符串化) ,而 JSON.stringify 则是更严格的 JSON 序列化。

但为什么 [1,2,3].toString() 返回的是 '1,2,3',而普通对象的 toString 返回 "[object Object]"?

因为不同的子类型重写了 toString 方法,用来细化类型的区分 。这也是为什么我们可以用 Object.prototype.toString.call(obj) 来精准判断一个变量的类型:

javascript

javascript 复制代码
Object.prototype.toString.call([])   // "[object Array]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call({})   // "[object Object]"

顺便提一句笔记里的重点:call 可以让一个方法借给其他对象使用,这是 JS 函数式特性的体现。

javascript

javascript 复制代码
let o = {
  name: '胡老板',
  say: function() {
    console.log('我是' + this.name);
  }
};

let obj = { name: '张三' };
o.say.call(obj); // '我是张三' ------ this 被指向了 obj

三、判断回文字符串

回文字符串:正着读和反着读都一样。比如 'abcba'、'racecar'。

解法一:API 流(简洁但不一定高效)

javascript

lua 复制代码
function isPalindrome(str) {
    return str === str.split('').reverse().join('');
}

解法二:双指针(推荐)

利用对称特性,从两端往中间比较:

javascript

ini 复制代码
function isPalindrome(str) {
    const len = str.length;
    for (let i = 0; i < len / 2; i++) {
        if (str[i] !== str[len - 1 - i]) {
            return false;
        }
    }
    return true;
}

小细节 :为什么把 len 存成变量而不是每次都 str.length?因为 str.length 在循环中每次访问都有开销(涉及包装类的临时转换),而存在栈内存的变量访问更快。虽然微乎其微,但好习惯要从细节养成。


四、进阶:最多删除一个字符的回文判断

这是回文字符串的经典衍生题,也是面试中的常客:

给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

比如 'abca',删除 'c' 或 'b' 后可以得到 'aba' 或 'aca',都是回文。

思路分析

双指针从两端向中间移动,遇到不匹配的字符时,有两种删除策略:

  • 删除左边的字符,检查 [i+1, j] 区间是否是回文
  • 删除右边的字符,检查 [i, j-1] 区间是否是回文

只要其中一种成立,就返回 true。

代码实现

javascript

ini 复制代码
function validPalindrome(s) {
    const len = s.length;
    let i = 0;
    let j = len - 1;

    while (i < j && s[i] === s[j]) {
        i++;
        j--;
    }

    // 删除左边一个,检查 [i+1, j]
    if (isPalindrome(i + 1, j)) {
        return true;
    }
    // 删除右边一个,检查 [i, j-1]
    if (isPalindrome(i, j - 1)) {
        return true;
    }

    // 辅助函数:检查 s 在 [i, j] 区间是否是回文
    function isPalindrome(i, j) {
        while (i < j) {
            if (s[i] !== s[j]) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }

    return false; // 两种删除策略都失败
}

举例理解

以 'aacvdafafdvcaa' 为例:

双指针一直向内移动,直到遇到第一对不相等的字符时停下,此时 i 和 j 指向的就是需要"二选一"删除的位置。然后分别尝试删左或删右,看剩下的部分是否回文。


写在最后

字符串算法看似简单,但要想写得优雅且考虑周全,需要对 JS 的数据类型、原型链、底层包装类等有深入理解。

这四道题从基础到进阶,正好构成了一个完整的学习路径:

  1. 反转字符串 ------ 熟悉数组和字符串的 API 配合
  2. 包装类机制 ------ 理解 JS 底层的设计哲学
  3. 回文判断 ------ 掌握双指针技巧
  4. 删除一个字符的回文判断 ------ 举一反三,灵活运用

希望这篇文章对你有所帮助。如果有什么问题或者想探讨更多细节,欢迎在评论区交流~

相关推荐
tangguofeng11 分钟前
不带头结点的链队操作集(不含InitFlag)(C语言版)
算法
苏打豆1 小时前
CRISP源码阅读——基于ROS2力矩反馈控制器与速度加速度零空间
c++·线性代数·算法·矩阵·机器人
蛋蛋的就会顺顺的2 小时前
hot100——矩阵
java·数据结构·算法·leetcode·力扣
老歌老听老掉牙2 小时前
麻花钻切屑形态演变的力学机制与临界条件分析
python·算法·钻头
zhangfeng11333 小时前
国产GPU/AI算力芯片现状(修订完整版 · 截至2026年9月
人工智能·算法·ai编程·npu
学代码的CJY3 小时前
从代码出发理解时间复杂度与空间复杂度
数据结构·算法
小溪学编程3 小时前
从 C++ 的规范变迁看语言发展
jvm·c++·面试
白帽攻防录3 小时前
SRC 挖洞:WSO2 JWT 算法混淆绕过深度复盘,CVE-2026-5430 不支持的算法怎么变成管理员
网络·算法·安全·网络安全·jwt
小O的算法实验室4 小时前
IEEE TEVC,基于精确与DQN群智能调度方法用于多目标异构USV
算法
ShineWinsu4 小时前
对于Redis:string类型的解析
java·c++·redis·分布式·缓存·面试·string