最近,我与一家公司进行了电话面试,并被问到一个有关堆栈的问题,我不知道该如何正确解决。这促使我加深了对堆栈的了解。
我被要求编写max函数在堆栈中找到最大值。
堆栈是一种数据结构,其中新的项目添加到顶部,项目也从顶部删除。这称为后进先出(LIFO)。
表示堆栈的一种方法是数组。我想象了一个数组,其中的项将添加到末尾,然后从末尾删除。
[2, 3, 3, 1, 1, 100, 200, 100, 400, 30]
30是堆栈的顶部,也是从堆栈中删除的第一个数字。
我的第一个显而易见的想法是遍历数组,存储当前的最大数字并在最后返回该数字。
// O(n)的算法
function find_max (arr) {
let max = Number.NEGATIVE_INFINITY
for (let i = 0, len = arr.length; i < len; i++) {
max = (arr[i] > max ? arr[i] : max)
}
return max
}
显然这不是面试官想要的答案,而是问我如何考虑性能的情况来解决这个问题。
我将用一个额外的堆栈来存储最大值。然后将从该额外堆栈中读取最高值,以了解当前的最大值。
class Stack {
constructor() {
this.data = [];
this.size = 0;
this.maxValues = [];
}
push(element) {
if (this.size === 0 || element >= this.findMax()) {
this.maxValues.push(element)
} else {
this.maxValues.push(this.findMax())
}
this.size += 1
this.data.push(element);
return this.data
}
pop() {
if (this.size > 0) {
this.size -= 1;
this.maxValues.pop()
return this.data.pop()
}
}
peek() {
return this.data[this.size - 1]
}
findMax() {
return this.maxValues[this.size - 1]
}
}
let stack = new Stack()
stack.push(5)
stack.push(5)
stack.push(7)
stack.push(3)
stack.push(4)
console.log(stack)
console.log("max", stack.findMax())
通过此实现,理论上要查找最大值的所有操作就是快速查找操作,以查找maxValues数组中的最后一个元素。通过索引查找数组中的元素的时间复杂度为O(1)。另外,用于从maxValues堆栈中添加和删除值的push和pop操作的时间复杂度为O(1)。这比循环遍历数组每次查找当前最大值要高效得多,后者可能是O(n),其中n是数组的长度。
前端精髓
与你分享web开发的乐趣
长按二维码关注我们