栈是一种比较常见的数据结构,虽然在js中没有原生的栈,但是实现起来也并不复杂,主要就是
push
,pop
,top
几个函数的实现。我这里说到的有序栈就是一种元素按照一定顺序排列的栈。主要的应用场景有:求数组中最小的K个数等。 有序栈的类实现方式
class Stack{
/**
* 构造函数,s用来存储数据,count用来记录栈的大小
*/
constructor(){
this.s = [];
this.count = 0;
}
/**
* 栈的push函数,往栈中添加数据
* @param num 需要存储到栈中的数据
*/
push(num) {
// 如果数据为空,不做操作
if(!num) return;
// 找到栈中大于num的数的下标
const index = this.s.findIndex((value, index) => value > num);
// 如果没有找到,说明栈中的元素都会小于num,直接添加到数组的最后面
if(index === -1) this.s.push(num);
else{
// 否则,插入第一个会大于num的元素位置
this.s.splice(index, 0, num);
}
// 栈大小增加1
++this.count;
}
/**
* 栈弹出元素,数组按从小到大排序的,直接把最大的元素弹出
*/
pop(){
this.s.pop();
--this.count;
}
/**
* 返回栈顶元素
* @returns 数组中最大的元素
*/
top() {
if(this.count >= 1) return this.s[this.count-1];
return undefined;
}
}
function kMin(arr, k){
const st = new Stack();
arr.forEach(item => {
// 如果栈的元素个数小于k,直接将数据添加到栈中
if(st.count < k){
st.push(item);
}else{
// 否则的话,如果元素小于栈顶元素,则将栈顶元素弹出,并将数据添加到栈中
if(item < st.top()){
st.pop();
st.push(item);
}
}
})
return st.s;
}
kMin([7,4,5,8,10,30], 2)
现在函数式编程比较流行,这里再给出函数式的实现方式。明显可以看出,函数式的实现方式更加简洁明了,对外暴露的变量和函数都通过return的方式。
function fStack(){
const arr = [];
const count = () => {
return arr.length;
}
const push = (num) => {
// 如果数据为空,不做操作
if(!num) return;
// 找到栈中大于num的数的下标
const index = arr.findIndex((value, index) => value > num);
// 如果没有找到,说明栈中的元素都会小于num,直接添加到数组的最后面
if(index === -1) arr.push(num);
else{
// 否则,插入第一个会大于num的元素位置
arr.splice(index, 0, num);
}
}
const pop = () => {
arr.pop();
}
const top = () => {
if(count >= 1) return arr[count-1];
return undefined;
}
return {
arr,
count,
push,
pop,
top
}
}
function kMin(arr, k){
const st = new fStack();
arr.forEach(item => {
// 如果栈的元素个数小于k,直接将数据添加到栈中
if(st.count() < k){
st.push(item);
}else{
// 否则的话,如果元素小于栈顶元素,则将栈顶元素弹出,并将数据添加到栈中
if(item < st.top()){
st.pop();
st.push(item);
}
}
})
return st.arr;
}
const res = kMin([7,4,5,8,10,30], 2)