栈的艺术:从“路明非”到 LeetCode,JavaScript 玩转数据结构

149 阅读4分钟

“主观上说它是一个栈,它就是一个栈。”——来自一位热爱算法的灵魂工程师

前言

你是否曾在算法面试中被“栈”这个词吓到?你是否觉得数据结构离生活很远?别怕,今天我们就用最接地气的方式,带你玩转 JavaScript 栈结构,让你在面试官面前自信满满,顺便还能收获一波“哈哈哈”!

一、栈是什么?一口气吃掉的薯片

栈(Stack),顾名思义,就是一摞东西。你可以把它想象成一桶薯片,吃的时候只能从最上面拿,想吃最下面的?对不起,先把上面的都吃完吧!

在编程世界里,栈的原则叫做“先进后出”(LIFO, Last In First Out)。你最后放进去的,最先拿出来。是不是和你小时候藏零食的套路很像?

JavaScript 中的栈

在 JavaScript 里,数组(Array)自带了栈的全部技能。只要你只用 pushpop,它就是一只正宗的“栈”:

let stack = [];
stack.push('路明非');
stack.push('楚子航');
stack.push('凯撒');
stack.push('芬格尔');
stack.push('陈墨瞳');

while (stack.length) {
    console.log(`我喜欢的角色${stack.pop()}`);
}

输出结果:

我喜欢的角色陈墨瞳
我喜欢的角色芬格尔
我喜欢的角色凯撒
我喜欢的角色楚子航
我喜欢的角色路明非

是不是很有画面感?你最喜欢的角色,最后一个出场!

二、栈的日常:括号匹配,程序员的“强迫症”

说到栈的经典应用,怎么能不提括号匹配?这可是面试官的心头好。

LeetCode 20:有效的括号

题目大意:给你一个只包含 ()[]{} 的字符串,判断它是不是“合法”的。

技术解析

  • 遇到左括号,入栈。
  • 遇到右括号,弹栈并检查是否匹配。
  • 最后栈空,说明完美匹配。

代码如下:

var isValid = function(s) {
    const obj = {
        '(': ')',
        '[': ']',
        '{': '}'
    }
    let stack = [];
    for (let i = 0; i < s.length; i++) {
        if (obj[s[i]] !== undefined){ // 左括号
            stack.push(s[i]);
        } else { // 右括号
            let left = stack.pop();
            if (obj[left] !== s[i]) {
                return false;
            }
        }
    }
    return stack.length === 0;
}

幽默解读

你可以把栈想象成一位“括号保安”,每次遇到左括号就登记入场,遇到右括号就核对离场。只要最后没人滞留,说明活动圆满结束!

三、栈的进阶:单调栈,温度也能玩算法

你以为栈只能玩括号?那你就小看它了。来看看 LeetCode 739:每日温度。

LeetCode 739:每日温度

题目大意:给你一组气温,问你每一天要等几天才会遇到更高的温度。

技术解析

  • 用一个“单调递减栈”存储下标。
  • 每次遇到更高温度,就弹栈并计算间隔天数。
  • 没有更高温度的,默认为 0。

代码如下:

var dailyTemperatures = function(temperatures) {
    const len = temperatures.length;
    const stack = [];
    const res = new Array(len).fill(0);

    for (let i = 0; i < len; i++) {
        while (stack.length && temperatures[i] > temperatures[stack[stack.length - 1]]) {
            const top = stack.pop();
            res[top] = i - top;
        }
        stack.push(i);
    }
    return res;
};

幽默解读

你可以把“单调栈”想象成一群怕热的小伙伴排队,每个人都在等比自己更热的那一天。只要遇到更热的,立刻“跑路”回家,顺便告诉你等了几天。最后还没等到的,只能默默接受现实。

四、数组与栈的“亲缘关系”

其实,栈就是“阉割版”的数组。数组能做的事多,栈只保留了 pushpop(或者 unshiftshift)。这就像你点了一份“精简套餐”,只保留了最核心的部分。

来自 readme.md 的总结:

# 栈
- 先进后出
1. 阉割版的数组 [], 只保留 push, pop 或者 unshift, shift

五、栈的面试哲学

面试官问你:“你了解栈吗?”你可以自信地说:

  • “栈就是一桶只能从上面拿薯片的零食桶!”
  • “在 JavaScript 里,数组就是我的栈,只要我只用 push 和 pop!”
  • “括号匹配、单调栈、逆序输出,统统不在话下!”

六、结语

栈结构看似简单,却蕴含着无穷的算法智慧。无论是括号匹配的“保安”,还是单调栈的“等温小队”,都让我们在算法的世界里游刃有余。

下次再遇到“栈”相关的面试题,记得带上这份幽默与自信,让面试官也忍不住为你点赞!


如果你觉得这篇文章有趣又有用,别忘了点赞、收藏、关注我!让我们一起在算法的路上,越走越远,越玩越嗨!