【问题标题】:Finding the maximum element in a stack in constant time在恒定时间内找到堆栈中的最大元素
【发布时间】:2016-11-12 01:29:40
【问题描述】:

在尝试从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 97
2
1 20
2
1 26
1 20
2
3
1 91
3

样本输出

26
91

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

  1. 使用一个向量来保存堆栈的状态
  2. 使用另一个向量来保存输入的最大值

我的解决方案如下 -

#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;
}

谁能帮我找出我的代码中遗漏的错误或极端情况,以便我修复它并通过所有测试用例?

【问题讨论】:

  • 您可以通过保持“运行”最大值来加快速度。使用包含推送的最大值的变量。输入命令 3 后,打印变量。当从堆栈中删除时,您可能必须确定最大值。
  • 您的解决方案也很有效!这与我最初的方法非常相似,只是每次输入option 3 时我都调用find_max(),这导致某些测试用例的HackerRank 平台超时。但是,在合并了您建议的优化之后(保持“运行”最大值并仅在我们从堆栈中弹出时调用find_max()),结果完美。谢谢。

标签: c++ algorithm vector stack


【解决方案1】:

这里有一个很酷的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])

【讨论】:

  • 你可以用一个栈来做,只需要一直推送max(data_to_be_added, stack[-1])。您不需要保留不是当前最大值的元素。
【解决方案2】:

问题是你只有在 x > mymax.back() 时才添加到 mymax。所以,如果 x == mymax.back() 你什么都不做。现在想象一下,将 1、3、3、3、3 插入到堆栈中。在这种情况下,您的“mymax”只有一个 3,一旦“删除”类型的查询到达,您的最大值将变为 1;然而,真正的答案是 3。解决这个问题会给你正确的答案。

但是,对于这样的问题,我通常在 C++ 中使用“多集”数据结构。并且任何插入堆栈的内容也都插入到多重集中(删除也是如此)。但是,多集可以更新 O(logn) 时间。并且它可以报告 O(1) 中的最大元素。

因为 N

请注意,multiset 与 set 数据结构非常相似,只是您可以使用 重复 数字,这对您的问题非常有帮助。

【讨论】:

  • 我有点不同意你的观点,原因是 multiset 是通过红黑树 /AVL 实现的,每个动作需要 O(lgn) 到目前为止不是一个恒定的时间,答案可以是 max-heap 和读取根->无论插入多少值或决定最大元素将位于向量/数组中的特定位置,因为它们提供了 O(1) (不是预期值),读取根将在 O(1)我会将我的元素插入到最大堆中,就是这样
  • Set 和 Multiset 可以在恒定时间内返回优先级最高的元素。实际上, *s.begin() 将返回具有最高优先级的元素。 (我们使用 * 来返回迭代器 s.begin() 的内容)。在set、multiset、map中删除和插入(都是红黑树)耗时O(logn)。
  • sry 你实际上是对的,set 和 multiset 是有序的,如果你在比较函数/函子中放了更大的值,你会在 s.begin() 中得到它,就像你说的那样!我的错误:)
猜你喜欢
  • 2016-08-12
  • 2018-10-08
  • 2018-10-07
  • 2014-05-07
  • 2012-08-29
  • 2019-03-25
  • 1970-01-01
  • 1970-01-01
  • 2020-05-08
相关资源
最近更新 更多