• 包含min函数的栈


    目标:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

    设计思路:     我们要做的是在我们每次数据入栈的时候,记录当前数据栈中最小值,并且在pop()出栈之后依然能找到最小值;

        方案①,如果只用一个 min 变量来保存每次入栈时候的最小值,那么出栈的时候,当前的最小值还是栈中的最小值吗?假设栈中的数据按入栈顺序依次为[ 2, 3, 5, 1 ] ,很明显此时记录的min值为1,那么当我们pop()出一条数据之后,堆栈变为 [ 2, 3, 5 ] ,此时的最小值应为2,但是记录的min值为1,最小值记录已丢失,此方案不通。

        方案②,基于方案①的问题,我们应该设计一个结构,能够保存我们每一步入栈的时候情况下的当前最小值。可能我们会想到用数组结构排序后取最小值,但是要保证时间复杂度为O(1),那么数组结构方案舍弃(没有一种数组排序为O(1)复杂度)。

        方案③,在这里我采用堆栈结构来保存记录最小值,为什么采用堆栈呢,堆栈结构有一个特点是保护现场和恢复现场的功能。想象一下,每次我们数据入栈时保存最小值,出栈的时候还要能恢复上一次的最小值,是不是和堆栈的这个特点不谋而合呢。所以我们采用堆栈结构。当然,在这里我们需要使用双倍的存储空间来实现功能,以空间换取时间╮(╯▽╰)╭。

    首先我们实现一个Stack结构,代码如下:

     1 class Stack {
     2     constructor() {
     3         this.stack = []
     4     }
     5     push(v) {
     6         this.stack.push(v)
     7     }
     8     pop() {
     9         this.stack.pop()
    10     }
    11     isEmpty() {
    12         return !this.count()
    13     }
    14     count() {
    15         return this.stack.length
    16     }
    17     top() {
    18         return this.stack[this.count() - 1]
    19     }
    20 }

    接着实现最小堆栈代码

     1 class MinStack {
     2     data_stack = new Stack() // 存放真正的栈数据
     3     min_stack = new Stack() // 存放最小值栈
     4     constructor() { }
     5     push(val) {
     6         const min_stack = this.min_stack;
     7         // 数据入栈
     8         this.data_stack.push(val);
     9         /* 在最小堆栈中记录每一次更新堆栈的当前情况下的最小值,
    10         即保证最小栈栈顶始终记录的是当前数据栈中最小的那个值,
    11         那么在每次pop的时候,最小栈栈顶记录的依旧记录的是最小值,
    12         就不用担心第二小值的问题啦 */
    13         if (min_stack.isEmpty() || val < min_stack.top()) {
    14             min_stack.push(val)
    15         } else {
    16             min_stack.push(min_stack.top())
    17         }
    18     }
    19     pop() {
    20         this.data_stack.pop()
    21         this.min_stack.pop()
    22     }
    23     min() {
    24         return this.min_stack.top()
    25     }
    26 }

    测试结果

    完整代码如下

    class Stack {
        constructor() {
            this.stack = []
        }
        push(v) {
            this.stack.push(v)
        }
        pop() {
            this.stack.pop()
        }
        isEmpty() {
            return !this.count()
        }
        count() {
            return this.stack.length
        }
        top() {
            return this.stack[this.count() - 1]
        }
    }
    
    class MinStack {
        data_stack = new Stack() // 存放真正的栈数据
        min_stack = new Stack() // 存放最小值栈
        constructor() { }
        push(val) {
            const min_stack = this.min_stack;
            // 数据入栈
            this.data_stack.push(val);
            /* 在最小堆栈中记录每一次更新堆栈的当前情况下的最小值,
            即保证最小栈栈顶始终记录的是当前数据栈中最小的那个值,
            那么在每次pop的时候,最小栈栈顶记录的依旧记录的是最小值,
            就不用担心第二小值的问题啦 */
            if (min_stack.isEmpty() || val < min_stack.top()) {
                min_stack.push(val)
            } else {
                min_stack.push(min_stack.top())
            }
        }
        pop() {
            this.data_stack.pop()
            this.min_stack.pop()
        }
        min() {
            return this.min_stack.top()
        }
    }
    
    const min_stack = new MinStack()
    
    min_stack.push(2)
    console.log(min_stack.min());
    min_stack.push(3)
    console.log(min_stack.min());
    min_stack.push(5)
    console.log(min_stack.min());
    min_stack.push(1)
    console.log(min_stack.min());
    min_stack.pop()
    console.log(min_stack.min());
    MinStack

    @萍2樱释 ღ( ´・ᴗ・` )

    打不死的小强
  • 相关阅读:
    Linux 线程间通信方式+进程通信方式 总结
    使用opencv第三方库的makefile文件示例
    rplidar SDK 二次开发---之获取目标信息(0.1)
    #include "Target_orientation.h"
    opencv —— 调用摄像头采集图像 VideoCapture capture(0);
    cmake 支持-lpthread
    ROS下sensor_msgs::ImagePtr到sensor_msgs::Image之间的转换
    JAVA 校验身份证号码工具类(支持15位和18位)
    python面向对象游戏练习:好人坏人手枪手榴弹
    python 私有属性的作用
  • 原文地址:https://www.cnblogs.com/mggahui/p/13380690.html
Copyright © 2020-2023  润新知