LeetCode 面试题 03.03. 堆盘子
题目
解题
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]