LeetCode《程序员面试金典》面试题 03.03. 堆盘子

这篇博客主要介绍了LeetCode上关于堆盘子的面试题,探讨了在JavaScript中如何实现push、pop操作,并针对是否允许中间stack不满的情况进行了详细解答,分别提供了两种解题思路。在实现过程中,特别注意了当capacity小于等于0时的特殊情况,以及在不允许中间stack不满的情况下如何调整元素位置。
摘要由CSDN通过智能技术生成

题目

在这里插入图片描述

解题

push 和 pop 不难实现,要注意的是若最后一个栈被填满,就需新建一个栈,再把元素 push 进去;最后一个元素 pop 出去后,若最后 一个栈为空 (执行出栈操作后),就必须从栈数组中移除这个栈。

popAt 的问题在于会选择任意的 stack 删除元素,中间的 stack 可能会不满或者因为空了要被删除。这里要讨论一下是否允许除最后一个 stack 外的其他 stack 不满?LeetCode 上是允许的,但是书上的解法是不允许的情况,所以每次在中间删除元素,都需要把后面的元素挪位。

需要特别注意当 capacity <= 0 的情况

解题一:允许中间 stack 不满

// javascript
/**
 * @param {number} cap
 */
var StackOfPlates = function(cap) {
    this.capacity = cap;
    this.stacks = [];
};

/** 
 * @param {number} val
 * @return {void}
 */
StackOfPlates.prototype.push = function(val) {
    if (this.capacity <= 0) return;
    let lastIdx = this.stacks.length - 1;
    if (lastIdx < 0 || this.stacks[lastIdx].length === this.capacity) {
        this.stacks.push([val]);
    }
    else {
        this.stacks[lastIdx].push(val);
    }
    return;
};

/**
 * @return {number}
 */
StackOfPlates.prototype.pop = function() {
    let lastIdx = this.stacks.length - 1;
    if (lastIdx < 0) return -1;
    let x = this.stacks[lastIdx].pop();
    if (this.stacks[lastIdx].length === 0) {
        this.stacks.pop();
    }
    return x;
};

/** 
 * @param {number} index
 * @return {number}
 */
StackOfPlates.prototype.popAt = function(index) {
    let lastIdx = this.stacks.length - 1;
    if (index < 0 || index > lastIdx) return -1;
    let x = this.stacks[index].pop();
    if (this.stacks[index].length === 0) {
        this.stacks.splice(index, 1);
    }
    return x;
};

解题二:不允许中间 stack 不满

在这里插入图片描述
仅仅需要改写 popAt 函数。

// javascript
StackOfPlates.prototype.popAt = function(index) {
    let lastIdx = this.stacks.length - 1;
    if (index < 0 || index > lastIdx) return -1;
    let x = this.stacks[index].pop();
    if (this.stacks[index].length === 0) {
        this.stacks.splice(index, 1);
    }
    // 添加的部分
    else {
        this.leftShift(index);
    }
    // 添加的部分
    return x;
};

StackOfPlates.prototype.leftShift = function(index) {
    let lastIdx = this.stacks.length - 1;
    // 如果 index = lastIdx,进不了 for 循环
    for (let i = index; i < lastIdx; i++) {
        let stackTmp = [];
        while (this.stacks[i + 1].length > 0) {
            stackTmp.push(this.stacks[i + 1].pop());
        }
        this.stacks[index].push(stackTmp.pop());
        while (stackTmp.length > 0) {
            this.stacks[index + 1].push(stackTmp.pop());
        }
    }
    // 最后一个stack只有一个元素的情况
    if (this.stacks[lastIdx].length === 0) this.stacks.pop();
    return;
};

或者

// javascript
/** 
 * @param {number} index
 * @return {number}
 */
StackOfPlates.prototype.popAt = function(index) {
    return this.leftShift(index, true);
};

StackOfPlates.prototype.leftShift = function(index, removeTop) {
    if (index < 0 || index > this.stacks.length - 1) return -1;
    let stack = this.stacks[index];
    let removeItem;
    if (removeTop === true) removeItem = stack.pop();
    else removeItem = this.removeBottom(stack);
    if (stack.length === 0) { // 若最后的stack只有一个元素,这个可以handle
        this.stacks.splice(index, 1);
    }
    else if (index < this.stacks.length - 1) {
        let v = this.leftShift(index + 1, false);
        stack.push(v);
    }
    return removeItem;
};

StackOfPlates.prototype.removeBottom = function(stack) {
    let stackTmp = [];
    while (stack.length > 0) {
        stackTmp.push(stack.pop());
    }
    let x = stackTmp.pop();
    while (stackTmp.length > 0) {
        stack.push(stackTmp.pop());
    }
    return x;
};

自己找了测试用例测了一下,得到预期结果。

["StackOfPlates", "push", "push", "push", "push", "popAt", "pop", "popAt", "popAt"]
[[2], [1], [2], [3], [4], [0], [], [0], [0]]
结果:[null,null,null,null,null,2,4,3,1]

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值