构造一个可以在固定时间内返回最小元素值的栈

我一开始没想太多,觉得把标准库里现有的数据结构拼一下,完全就可以了,这是我的代码:

class MinStack {
private:
    multiset<int> sortedElems;
    list<int>     stack;
public:
    void push(int x) {
        sortedElems.insert(x);
        stack.push_back(x);
    }

    void pop() {
        if (stack.empty()){
            return;
        }
        sortedElems.erase(sortedElems.find(stack.back()));
        stack.pop_back();
    }

    int top() {
        return stack.back();
    }

    int getMin() {
        return *sortedElems.cbegin();
    }
};

这个思路有点偷懒,就是你既然要求返回最小元素所用的时间是固定的,那么原先理论上需要用来查找的开销我就挪到别的地方去,没错,我把它们分摊到了 pop() he push() 上。

但毕竟我的这个算法很愚蠢,所以就算是返回最小值的时间变短了,但总时间还是很长,效率低下, 共用了 54ms。

当我的方法不算是最快的那一种的时候,我就会看一下讨论区里其他朋友的方法,结果果然发现了更高效的方法,原代码是 Java 版本,我改写了自己的一份 C++ 版本:

class MinStack {
private:
    long long min = 0;
    stack<long long> _stack;
public:
    void push(int x) {
        auto&& n = static_cast<long long>(x);
        if (_stack.empty()) {
            _stack.push(0L);
            min = n;
            return;
        }
        _stack.push(n - min);
        if (n < min){
            min = n;
        }
    }

    void pop() {
        if (_stack.empty()){
            return;
        }

        auto popedNum = _stack.top();
        if (popedNum < 0L){
            min -= popedNum;
        }

        _stack.pop();
    }

    int top() {
        auto topNum = _stack.top();
        if (topNum > 0) {
            return static_cast<int>(min + topNum);
        }
        return static_cast<int>(min);
    }

    int getMin() {
        return static_cast<int>(min);
    }
};

这个算法很有意思,是一种空间换时间的策略,我之前的想法中,最小值和栈中存储的值是割裂开的,存储是存储,然后再单独求出最小值。

而这种方法就不同了,它是把最小值与每个值在 push() 时通过运算建立联系,并在 pop() 时通过逆运算求得原先的值,因此所用时间只有 28ms。

时间: 2024-10-24 13:24:56

构造一个可以在固定时间内返回最小元素值的栈的相关文章

c编程:求出4&amp;#215;4矩阵中最大和最小元素值及其所在行下标和列下标,求出两条主对角线元素之和。

//求出4×4矩阵中最大和最小元素值及其所在行下标和列下标,求出两条主对角线元素之和 #include <stdio.h> int main() { int sum=0; int max,min; int max1,max2;//记录最大值的坐标 int min1,min2;//记录最小值的坐标 int i,j; int a[4][4]; //为数组赋值 for(i=0;i<4;i++) { for(j=0;j<4;j++) { scanf("%d",&

c编程:求出4&#215;4矩阵中最大和最小元素值及其所在行下标和列下标,求出两条主对角线元素之和。

//求出4×4矩阵中最大和最小元素值及其所在行下标和列下标,求出两条主对角线元素之和 #include <stdio.h> int main() { int sum=0; int max,min; int max1,max2;//记录最大值的坐标 int min1,min2;//记录最小值的坐标 int i,j; int a[4][4]; //为数组赋值 for(i=0;i<4;i++) { for(j=0;j<4;j++) { scanf("%d",&

O(1)时间复杂度实现入栈、出栈、获得栈中最小元素、获得栈中最大元素(转)

题目要求:定义栈的数据结构,添加min().max()函数(动态获取当前状态栈中的最小元素.最大元素),要求push().pop().min().max()的时间复杂度都是O(1). 思路解析:根据栈的后进先出特性,增加辅助栈,来存储当前状态下数据栈中的最小.最大元素. 原文:http://blog.csdn.net/happy309best/article/details/47725935

笔试算法题(05):转换BST为双向链表 &amp; 查找栈中的最小元素

出题:把二元查找树转变成排序的双向链表.输入一棵二元查找树,要求将该二元查找树按照中序转换成一个排序的双向链表,要求不能创建任何新的节点,只能调整指针的指向: 分析: 递归的思路,当前节点需要进行的处理,并使用递归调用和返回值将子问题链接起来: 首先明白二元查找树的特性,变成有序双向链表后当前根节点的左节点为其原来左子树的最右节点,右节点为其原来右子树的最左节点:因此策略就是针对当前根节点索引的子树,首先判断其为上层节点的右子树还是左子树,从而决定返回最右还是最右节点:然后再递归处理当前根节点的

设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈

小结: 1. 常数时间内检索到最小元素 最小栈 - 力扣(LeetCode)https://leetcode-cn.com/problems/min-stack/ 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈. push(x) -- 将元素 x 推入栈中. pop() -- 删除栈顶的元素. top() -- 获取栈顶元素. getMin() -- 检索栈中的最小元素. 示例: MinStack minStack = new MinStack(); minSt

17、把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. eg: 输入 3 4 5 1 2 输出 1 思路:用二分法查找最小元素 三种情况: (1)rotateArray[mid] >rotateArray[high]: like:[x,x,x,6,x,x,2],此时最小数字一

一、实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作

请指教交流! 1 package com.it.hxs.c01; 2 3 import java.util.Stack; 4 5 /* 6 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作 7 */ 8 public class GetMinStack { 9 10 public static void main(String args[]) { 11 GetMinStack demoStack = new GetMinStack(); 12 demoStack.pus

构造一个随机发生器

http://m.blog.csdn.net/blog/u012605629/40406577 构造一个随机发生器 2014-10-23阅读83 评论0 2.已知一随机发生器,产生0的概率是p,产生1的概率是1-p,现在要你构造一个发生器,使得它构造0和1的概率均为 1/2:构造一个发生器,使得它构造1.2.3 的概率均为 1/3: ...,构造一个发生器,使得它构造 1.2.3....n 的概率均为1/n,要求复杂度最低. /* 2.已知一随机发生器,产生0的概率是p,产生1的概率是1-p,

输出一个为递增排序数组的旋转数组中的最小元素——8

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为数组{1, 2,3, 4, 5}的一个旋转,该数组的最小值为1. 当然了,将数组遍历一遍肯定能找出最小值,但其时间复杂度为O(N),效率是最低的,因此,应该有一种更高效的解决办法. 因为原数组是递增的,因此数组的第一个元素一定是最小值,而旋转之后,其最小值就会成为旋转的分界点,因此,查找一个旋转之后数组的最小值可以变成查找一个旋转数组的旋转点