在恒定时间内查找堆栈中的最大元素

时间:2016-07-09 17:11:03

标签: c++ algorithm vector stack

在尝试从HackerRank解决此问题时,我编写了以下代码,该代码通过了22/27测试用例。不幸的是,我无法访问失败的测试用例。

问题

您有一个空序列,您将获得 N 查询。每个查询都是以下三种类型之一:

  

1 x =>将元素x推入堆栈。
2 =>删除堆栈顶部的元素。
3 =>打印堆栈中的最大元素。

输入格式
第一行输入包含一个整数 N 。下一个 N 行每个都包含上述查询。 (保证每个查询都有效)

约束
1 <= N <= 10^5
1 <= x <= 10^9
1 <= type <= 3

输出格式
对于每种 3 查询,请在新行上打印堆栈中的最大元素。

示例输入

  

10
1 9 97
2
1 20 2 2 1 26一1 20
2 <3 /> 1 91
3

示例输出

  

26
91

我解决这个问题的方法是 -

  1. 使用一个向量来保持堆栈状态
  2. 使用另一个向量来保存输入的最大值
  3. 我的解决方案如下 -

    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main() {
        /* Enter your code here. Read input from STDIN. Print output to STDOUT */   
        vector<int> myvect;        /* Vector to hold the inputs */
        vector<int> mymax;         /* Vector to hold max elements */
        unsigned times;
        unsigned type;
        unsigned x;
        cin >> times;
        if (times <= 100000) {
            for (unsigned i = 0; i < times; i++) {
                cin >> type;
                if (type >= 1 && type <= 3) {
                    switch (type) {
                        case 1:
                            cin >> x;
                            if (x <= 1000000000) {
                                myvect.push_back(x);
                                if (mymax.empty())
                                    mymax.push_back(x);
                                else if (x > mymax.back())
                                        mymax.push_back(x);
                            }
                            break;
                        case 2:
                            if (!myvect.empty()) {
                                if (!mymax.empty() && (myvect.back() == mymax.back()))
                                    mymax.pop_back();
                                myvect.pop_back();
                            }
                            break;
                        case 3:
                            cout << mymax.back() << endl;
                            break;
                        default:
                            cout << "We should not get in here" << endl;
                    }
                }
            }
        }
        return 0;
    }
    

    有人可以帮我弄清楚我在代码中遗漏的错误或角落情况,以便我可以修复它并通过所有测试用例吗?

2 个答案:

答案 0 :(得分:1)

问题是如果x&gt;你只能添加到mymax mymax.back()。所以,如果x == mymax.back()你什么都不做。现在想象一下,将1,3,3,3,3插入堆栈中。在这种情况下,你的&#34; mymax&#34;只有一个3并且只要查询类型&#34;删除&#34;到达你的最大值将变为1;但是,真正的答案是3.解决这个问题会给你正确答案。

然而,对于这样的问题,我通常使用&#34; multiset&#34; c ++中的数据结构。并且插入到堆栈中的任何内容也会插入到multiset中(同样用于删除)。但是,multiset可以更新O(logn)时间。并且它可以报告O(1)中的最大元素。

因为N <= 10 ^ 5。该算法的复杂性为O(N log N),这仍然是非常合理的。

请注意,multiset与设置数据结构非常相似,但您可以使用重复数字,但问题非常有用。

答案 1 :(得分:0)

这是一个很酷的python解决方案,你只需要使用两个堆栈。

import sys

if __name__ == "__main__":
    stack = []
    stack_for_max = [-sys.maxsize]

    for i in range(0, int(input())):
        data = str(input())
        if " " in data:
            data_to_be_added = int(data.split(" ")[1])
            stack.append(data_to_be_added)

            if data_to_be_added >= stack_for_max[-1]:
                stack_for_max.append(data_to_be_added)

        elif data == "2":
            top_of_the_stack = stack.pop()
            if top_of_the_stack == stack_for_max[-1]:
                stack_for_max.pop()

        else:
            print(stack_for_max[-1])