【问题标题】:Next Greater Element下一个更大的元素
【发布时间】:2019-11-29 14:11:04
【问题描述】:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;

int main() {
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        int arr[n];
        for (int i = 0; i < n; i++)
        {
            cin >> arr[i];
        }
        stack<int>s;
        stack<int>q;
        for (int i = n - 1; i > 0; i--)
        {
            s.push(arr[i]);
        }
        while (!s.empty())
        {
            int a = s.top();
            s.pop();
            int flag = 0;
            while (!s.empty())
            {
                int p = s.top();
                if (a >= p)
                {
                    q.push(p);
                    s.pop();
                }
                else {
                    cout << p;
                    flag = 1;
                    break;
                }
                p = s.top();
            }
            if (flag == 0)
            {
                cout << -1;
            }
            while (!q.empty())
            {
                s.push(q.top());
                q.pop();
            }

        }
    }
    return 0;
}

给定一个数组,打印每个元素的下一个更大元素 (NGE)。元素 x 的下一个更大元素是数组中 x 右侧的第一个更大元素。对于不存在更大元素的元素,将下一个更大元素视为-1。 为什么这段代码会出现分段错误?

【问题讨论】:

  • 可能不相关。 int n; cin&gt;&gt;n; int arr[n]; 不是合法的 C++。在 C++ 中数组边界必须是编译时常量,但在上面的代码中n 是一个变量。
  • int arr[n]; 替换为vector&lt;int&gt; arr(n);,这至少是合法的C++ 并且可能会解决问题。
  • @J.Soumya 为什么要使用堆栈?只使用循环会更简单吗?
  • 什么是#include&lt;bits/stdc++.h&gt;?它不是标准标题
  • 我猜使用循环会花费更多时间。

标签: c++ arrays loops


【解决方案1】:

改变这个:

for (int i = n - 1; i > 0; i--)

到这里:

for (int i = n - 1; i >= 0; i--)

因为您想将所有元素推入堆栈。

之后,对于这个输入:

1
3
1
2
3

我得到了预期的输出:

23-1

注意:正如@John 所说,p = s.top(); 什么都不做,因此可以安全地删除它(因为无论如何p 都会超出范围)。

【讨论】:

    【解决方案2】:
    p=s.top();
    

    我怀疑这里崩溃了。不能保证 s 在此时不为空。

    由于p 是一个即将超出范围的局部变量,这行代码没有任何作用(除了可能使程序崩溃)。可以安全移除。

    【讨论】:

    • 还有。 . ? :) 我的意思是,无论如何,我认为这不会给出正确的结果。虽然 OP 询问它在哪里崩溃......
    • 那行代码什么都不做,因为您即将退出声明p 的范围。你可以写p = 999;,这完全没有区别。
    • John 我同意,但是 OP 的代码存在一个根本问题。请看我的answer。我的意思是是的,你说的代码没有效果,但不是导致问题的原因。
    • 它现在给出了正确的结果,但是当它给出 TLE 时我应该如何优化它??
    【解决方案3】:

    在我之前的answer 中解决了这个问题后,可以根据@VladFromMoscow 的评论,使用loops 来实现这一点,而无需使用两个额外的数据结构。

    策略可能如下:

    For every element `e` in the array
      Check if next element of `e` is greater than `e`
        If yes, print it
    

    这意味着使用两个 for 循环,其中第一个循环将扫描整个数组。第二个循环将从e 的下一个元素开始扫描数组,直到数组的末尾。

    注意:您可以跳过第一个循环中的最后一个元素,因为它保证没有任何下一个元素(因此也没有更大的下一个元素)。

    但是,您可能需要存储这些更大的元素,并且肯定可以为此使用堆栈(LIFO 数据结构),但我发现使用 FIFO 数据结构更自然,例如队列.当然也可以使用数组。

    请注意,即使在您需要存储元素的情况下,通过这种基于循环的方法,您也可以使用 一个 额外的数据结构,而不是两个(如您的代码中那样)。

    例子:

    #include <iostream>
    #include <queue>
    using namespace std;
    
    int main(void)
    {
      int n;
      cin >> n;
      if(!n)
      {
        cout << "Array will be empty, exiting..\n";
        return 1;
      }
      int arr[n];
      for (int i = 0; i < n; i++)
      {
        cin >> arr[i];
      }
      queue<int> q;
      // start 1st element until pre-last.
      for(int i = 0; i < n - 1; ++i)
      {
        // start from next element of i-th element, until last.
        for(int j = i + 1; j < n; ++j)
        {
          if(arr[j] > arr[i])
          {
            q.push(arr[j]);
            break;
          }
        }
      }
      while(!q.empty())
      {
        cout << q.front() << ", ";
        q.pop();
      }
      // last element of array does not have any next element
      cout << "-1\n";
      return 0;
    }
    

    输入:

    3 1 2 3

    输出:

    2、3、-1

    注意:如果您不需要存储下一个更大的元素,则只需打印arr[j] 而不是执行q.push(arr[j]);,然后是break 循环。

    【讨论】:

      【解决方案4】:

      Python 中的解决方案

      a = [1, 5, 2, 9]
      
      a.reverse()
      
      if a == sorted(a):
          print("No")
      else:
          for i in range(len(a)-1):
              if a[i] > a[i+1]:
                  a[i], a[i+1] = a[i+1], a[i]
                  break
      
      a.reverse()
      print(a)
      

      输出:[1, 5, 9, 2]

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-02
        • 2014-07-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多