📜  右侧 NGE 的数量

📅  最后修改于: 2021-10-27 07:15:09             🧑  作者: Mango

给定一个包含 n 个整数和 q 个查询的数组,打印给定索引元素右侧的下一个更大元素的数量。
例子:

Input: a[] = {3, 4, 2, 7, 5, 8, 10, 6}  
              q = 2 
              index = 0, 
              index = 5
Output: 6
        1 
Explanation:
The next greater elements
to the right of 3(index 0) are 4,7,5,8,10,6. 
The next greater elements to the right
of 8(index 5) are 10.

一种天真的方法是对每个查询从索引到结尾进行迭代,并找出右边的下一个更大元素的数量。这将不够高效,因为我们运行两个嵌套循环

时间复杂度: O(N) 来回答一个查询。
辅助空间: O(1)

更好的方法是存储每个元素的下一个更大的索引,并为每个从索引迭代的查询运行一个循环,并将递增的计数器保持为 j = next[i]。这将避免检查所有元素,并会直接跳转到每个元素的下一个更大的元素。但这在 1 2 3 4 5 6 这样的情况下效率不够高,在这种情况下,下一个更大的元素按顺序增加,最终每个查询都需要 O(n)。

时间复杂度: O(N) 来回答一个查询。
辅助空间: O(N) 表示下一个更大的元素。

有效的方法是使用 next[] 数组中的下一个更大的元素来存储下一个更大的元素索引。然后创建一个从 n-2 开始的 dp[] 数组,因为第 n-1 个索引将没有其右侧的元素并且 dp[n-1] = 0。从后面遍历时,我们使用动态规划来计算元素的数量在我们使用 memoization 作为 dp[next[i]] 的右侧,它为我们提供了当前元素的下一个较大元素右侧的数字计数,因此我们将其加 1。如果 next[i]=-1 则右边没有任何元素,因此 dp[i]=0。 dp[index] 存储右侧下一个更大元素的数量。

下面是上述方法的实现。

C++
#include 
using namespace std;
 
// array to store the next greater element index
void fillNext(int next[], int a[], int n)
{
    // use of stl stack in c++
    stack s;
 
    // push the 0th index to the stack
    s.push(0);
 
    // traverse in the loop from 1-nth index
    for (int i = 1; i < n; i++) {
 
        // iterate till loop is empty
        while (!s.empty()) {
 
            // get the topmost index in the stack
            int cur = s.top();
 
            // if the current element is greater
            // then the top index-th element, then
            // this will be the next greatest index
            // of the top index-th element
            if (a[cur] < a[i]) {
 
                // initialize the cur index position's
                // next greatest as index
                next[cur] = i;
 
                // pop the cur index as its greater
                // element has been found
                s.pop();
            }
 
            // if not greater then break
            else
                break;
        }
 
        // push the i index so that its next greatest
        // can be found
        s.push(i);
    }
 
    // iterate for all other index left inside stack
    while (!s.empty()) {
 
        int cur = s.top();
 
        // mark it as -1 as no element in greater
        // then it in right
        next[cur] = -1;
 
        s.pop();
    }
}
 
// Function to count the number of
// next greater numbers to the right
void count(int a[], int dp[], int n)
{
    // initializes the next array as 0
    int next[n];
    memset(next, 0, sizeof(next));
 
    // calls the function to pre-calculate
    // the next greatest element indexes
    fillNext(next, a, n);
 
    for (int i = n - 2; i >= 0; i--) {
 
        // if the i-th element has no next
        // greater element to right
        if (next[i] == -1)
            dp[i] = 0;
 
        // Count of next greater numbers to right.
        else
            dp[i] = 1 + dp[next[i]];
    }
}
 
// answers all queries in O(1)
int answerQuery(int dp[], int index)
{
    // returns the number of next greater
    // elements to the right.
    return dp[index];
}
 
// driver program to test the above function
int main()
{
    int a[] = { 3, 4, 2, 7, 5, 8, 10, 6 };
    int n = sizeof(a) / sizeof(a[0]);
 
    int dp[n];
 
    // calls the function to count the number
    // of greater elements to the right for
    // every element.
    count(a, dp, n);
 
    // query 1 answered
    cout << answerQuery(dp, 3) << endl;
 
    // query 2 answered
    cout << answerQuery(dp, 6) << endl;
 
    // query 3 answered
    cout << answerQuery(dp, 1) << endl;
 
    return 0;
}


Java
// Java program to print number of NGEs to the right
import java.util.*;
 
class GFG
{
 
// array to store the next greater element index
static void fillNext(int next[], int a[], int n)
{
    // Use stack
    Stack s = new Stack();
 
    // push the 0th index to the stack
    s.push(0);
 
    // traverse in the loop from 1-nth index
    for (int i = 1; i < n; i++)
    {
 
        // iterate till loop is empty
        while (s.size() > 0)
        {
 
            // get the topmost index in the stack
            int cur = s.peek();
 
            // if the current element is greater
            // then the top index-th element, then
            // this will be the next greatest index
            // of the top index-th element
            if (a[cur] < a[i])
            {
 
                // initialize the cur index position's
                // next greatest as index
                next[cur] = i;
 
                // pop the cur index as its greater
                // element has been found
                s.pop();
            }
 
            // if not greater then break
            else
                break;
        }
 
        // push the i index so that its next greatest
        // can be found
        s.push(i);
    }
 
    // iterate for all other index left inside stack
    while (s.size() > 0)
    {
 
        int cur = s.peek();
 
        // mark it as -1 as no element in greater
        // then it in right
        next[cur] = -1;
 
        s.pop();
    }
}
 
// function to count the number of
// next greater numbers to the right
static void count(int a[], int dp[], int n)
{
    // initializes the next array as 0
    int next[] = new int[n];
    for(int i = 0; i < n; i++)
    next[i] = 0;
     
    // calls the function to pre-calculate
    // the next greatest element indexes
    fillNext(next, a, n);
 
    for (int i = n - 2; i >= 0; i--)
    {
 
        // if the i-th element has no next
        // greater element to right
        if (next[i] == -1)
            dp[i] = 0;
 
        // Count of next greater numbers to right.
        else
            dp[i] = 1 + dp[next[i]];
    }
}
 
// answers all queries in O(1)
static int answerQuery(int dp[], int index)
{
    // returns the number of next greater
    // elements to the right.
    return dp[index];
}
 
// driver code
public static void main(String args[])
{
    int a[] = { 3, 4, 2, 7, 5, 8, 10, 6 };
    int n = a.length;
 
    int dp[] = new int[n];
 
    // calls the function to count the number
    // of greater elements to the right for
    // every element.
    count(a, dp, n);
 
    // query 1 answered
    System.out.println(answerQuery(dp, 3));
 
    // query 2 answered
    System.out.println( answerQuery(dp, 6));
     
    // query 3 answered
    System.out.println( answerQuery(dp, 1) );
 
}
}
 
// This code is contributed by Arnab Kundu


C#
// C# program to print number of
// NGEs to the right
using System;
using System.Collections;
 
class GFG
{
 
// array to store the next greater element index
static void fillNext(int []next, int []a, int n)
{
    // Use stack
    Stack s = new Stack();
 
    // Push the 0th index to the stack
    s.Push(0);
 
    // traverse in the loop from 1-nth index
    for (int i = 1; i < n; i++)
    {
 
        // iterate till loop is empty
        while (s.Count > 0)
        {
 
            // get the topmost index in the stack
            int cur = (int)s.Peek();
 
            // if the current element is greater
            // then the top index-th element, then
            // this will be the next greatest index
            // of the top index-th element
            if (a[cur] < a[i])
            {
 
                // initialize the cur index position's
                // next greatest as index
                next[cur] = i;
 
                // Pop the cur index as its greater
                // element has been found
                s.Pop();
            }
 
            // if not greater then break
            else
                break;
        }
 
        // Push the i index so that its next
        // greatest can be found
        s.Push(i);
    }
 
    // iterate for all other index
    // left inside stack
    while (s.Count > 0)
    {
 
        int cur =(int) s.Peek();
 
        // mark it as -1 as no element in
        // greater then it in right
        next[cur] = -1;
 
        s.Pop();
    }
}
 
// function to count the number of
// next greater numbers to the right
static void count(int []a, int []dp, int n)
{
    // initializes the next array as 0
    int []next = new int[n];
    for(int i = 0; i < n; i++)
        next[i] = 0;
     
    // calls the function to pre-calculate
    // the next greatest element indexes
    fillNext(next, a, n);
 
    for (int i = n - 2; i >= 0; i--)
    {
 
        // if the i-th element has no next
        // greater element to right
        if (next[i] == -1)
            dp[i] = 0;
 
        // Count of next greater numbers to right.
        else
            dp[i] = 1 + dp[next[i]];
    }
}
 
// answers all queries in O(1)
static int answerQuery(int []dp, int index)
{
    // returns the number of next greater
    // elements to the right.
    return dp[index];
}
 
// Driver code
public static void Main(String []args)
{
    int []a = { 3, 4, 2, 7, 5, 8, 10, 6 };
    int n = a.Length;
 
    int []dp = new int[n];
 
    // calls the function to count the number
    // of greater elements to the right for
    // every element.
    count(a, dp, n);
 
    // query 1 answered
    Console.WriteLine(answerQuery(dp, 3));
 
    // query 2 answered
    Console.WriteLine( answerQuery(dp, 6));
     
    // query 3 answered
    Console.WriteLine( answerQuery(dp, 1));
}
}
 
// This code is contributed by Arnab Kundu


Javascript


C++
#include 
using namespace std;
 
vector no_NGN(int arr[], int n)
{
    vector nxt;
 
    // use of stl stack in c++
    stack s;
 
    nxt.push_back(0);
    // push the (n-1)th index to the stack
    s.push(n - 1);
 
    // traverse in reverse order
    for (int i = n - 2; i >= 0; i--) {
        while (!s.empty() && arr[i] >= arr[s.top()])
            s.pop();
 
         
        // if no element is greater than arr[i] the
        // number of NGEs to right is 0
        if (s.empty())
            nxt.push_back(0);
         
        else
         
            // number of NGEs to right of arr[i] is
            // one greater than the number of NGEs to right
            // of higher number to its right
            nxt.push_back(nxt[n - s.top() - 1] + 1);
         
        s.push(i);
    }
 
    // reverse again because values are in reverse order
    reverse(nxt.begin(), nxt.end());
 
    // returns the vector of number of next
    // greater elements to the right of each index.
    return nxt;
}
 
int main()
{
    int n = 8;
 
    int arr[] = { 3, 4, 2, 7, 5, 8, 10, 6 };
 
    vector nxt = no_NGN(arr, n);
 
    // query 1 answered
    cout << nxt[3] << endl;
 
    // query 2 answered
    cout << nxt[6] << endl;
 
    // query 3 answered
    cout << nxt[1] << endl;
 
    return 0;
}


Java
import java.util.*;
class GFG{
 
static Vector no_NGN(int arr[], int n)
{
    Vector nxt = new Vector<>();
 
    // use of stl stack in Java
    Stack s = new Stack<>();
    nxt.add(0);
   
    // push the (n-1)th index to the stack
    s.add(n - 1);
 
    // traverse in reverse order
    for (int i = n - 2; i >= 0; i--)
    {
        while (!s.isEmpty() && arr[i] >= arr[s.peek()])
            s.pop();
 
         
        // if no element is greater than arr[i] the
        // number of NGEs to right is 0
        if (s.isEmpty())
            nxt.add(0);
         
        else
         
            // number of NGEs to right of arr[i] is
            // one greater than the number of NGEs to right
            // of higher number to its right
            nxt.add(nxt.get(n - s.peek() - 1 ) + 1);
         
        s.add(i);
    }
 
    // reverse again because values are in reverse order
    Collections.reverse(nxt);
 
    // returns the vector of number of next
    // greater elements to the right of each index.
    return nxt;
}
 
// Driver code
public static void main(String[] args)
{
    int n = 8;
    int arr[] = { 3, 4, 2, 7, 5, 8, 10, 6 };
    Vector nxt = no_NGN(arr, n);
   
    // query 1 answered
    System.out.print(nxt.get(3) +"\n");
 
    // query 2 answered
    System.out.print(nxt.get(6) +"\n");
 
    // query 3 answered
    System.out.print(nxt.get(1) +"\n");
}
}
 
// This code is contributed by Rajput-Ji


C#
using System;
using System.Collections.Generic;
public class GFG{
static List no_NGN(int []arr, int n)
{
    List nxt = new List();
 
    // use of stl stack in Java
    Stack s = new Stack();
    nxt.Add(0);
   
    // push the (n-1)th index to the stack
    s.Push(n - 1);
 
    // traverse in reverse order
    for (int i = n - 2; i >= 0; i--)
    {
        while (s.Count!=0 && arr[i] >= arr[s.Peek()])
            s.Pop();
 
         
        // if no element is greater than arr[i] the
        // number of NGEs to right is 0
        if (s.Count == 0)
            nxt.Add(0);
         
        else
         
            // number of NGEs to right of arr[i] is
            // one greater than the number of NGEs to right
            // of higher number to its right
            nxt.Add(nxt[n - s.Peek() - 1 ] + 1);
         
        s.Push(i);
    }
 
    // reverse again because values are in reverse order
    nxt.Reverse();
 
    // returns the vector of number of next
    // greater elements to the right of each index.
    return nxt;
}
 
// Driver code
public static void Main(String[] args)
{
    int n = 8;
    int []arr = { 3, 4, 2, 7, 5, 8, 10, 6 };
    List nxt = no_NGN(arr, n);
   
    // query 1 answered
    Console.Write(nxt[3] +"\n");
 
    // query 2 answered
    Console.Write(nxt[6] +"\n");
 
    // query 3 answered
    Console.Write(nxt[1] +"\n");
}
}
 
// This code iscontributed by aashish1995


Javascript


输出
2
0
3

时间复杂度: O(1) 来回答一个查询。
辅助空间: O(n)
替代较短的实现

C++

#include 
using namespace std;
 
vector no_NGN(int arr[], int n)
{
    vector nxt;
 
    // use of stl stack in c++
    stack s;
 
    nxt.push_back(0);
    // push the (n-1)th index to the stack
    s.push(n - 1);
 
    // traverse in reverse order
    for (int i = n - 2; i >= 0; i--) {
        while (!s.empty() && arr[i] >= arr[s.top()])
            s.pop();
 
         
        // if no element is greater than arr[i] the
        // number of NGEs to right is 0
        if (s.empty())
            nxt.push_back(0);
         
        else
         
            // number of NGEs to right of arr[i] is
            // one greater than the number of NGEs to right
            // of higher number to its right
            nxt.push_back(nxt[n - s.top() - 1] + 1);
         
        s.push(i);
    }
 
    // reverse again because values are in reverse order
    reverse(nxt.begin(), nxt.end());
 
    // returns the vector of number of next
    // greater elements to the right of each index.
    return nxt;
}
 
int main()
{
    int n = 8;
 
    int arr[] = { 3, 4, 2, 7, 5, 8, 10, 6 };
 
    vector nxt = no_NGN(arr, n);
 
    // query 1 answered
    cout << nxt[3] << endl;
 
    // query 2 answered
    cout << nxt[6] << endl;
 
    // query 3 answered
    cout << nxt[1] << endl;
 
    return 0;
}

Java

import java.util.*;
class GFG{
 
static Vector no_NGN(int arr[], int n)
{
    Vector nxt = new Vector<>();
 
    // use of stl stack in Java
    Stack s = new Stack<>();
    nxt.add(0);
   
    // push the (n-1)th index to the stack
    s.add(n - 1);
 
    // traverse in reverse order
    for (int i = n - 2; i >= 0; i--)
    {
        while (!s.isEmpty() && arr[i] >= arr[s.peek()])
            s.pop();
 
         
        // if no element is greater than arr[i] the
        // number of NGEs to right is 0
        if (s.isEmpty())
            nxt.add(0);
         
        else
         
            // number of NGEs to right of arr[i] is
            // one greater than the number of NGEs to right
            // of higher number to its right
            nxt.add(nxt.get(n - s.peek() - 1 ) + 1);
         
        s.add(i);
    }
 
    // reverse again because values are in reverse order
    Collections.reverse(nxt);
 
    // returns the vector of number of next
    // greater elements to the right of each index.
    return nxt;
}
 
// Driver code
public static void main(String[] args)
{
    int n = 8;
    int arr[] = { 3, 4, 2, 7, 5, 8, 10, 6 };
    Vector nxt = no_NGN(arr, n);
   
    // query 1 answered
    System.out.print(nxt.get(3) +"\n");
 
    // query 2 answered
    System.out.print(nxt.get(6) +"\n");
 
    // query 3 answered
    System.out.print(nxt.get(1) +"\n");
}
}
 
// This code is contributed by Rajput-Ji

C#

using System;
using System.Collections.Generic;
public class GFG{
static List no_NGN(int []arr, int n)
{
    List nxt = new List();
 
    // use of stl stack in Java
    Stack s = new Stack();
    nxt.Add(0);
   
    // push the (n-1)th index to the stack
    s.Push(n - 1);
 
    // traverse in reverse order
    for (int i = n - 2; i >= 0; i--)
    {
        while (s.Count!=0 && arr[i] >= arr[s.Peek()])
            s.Pop();
 
         
        // if no element is greater than arr[i] the
        // number of NGEs to right is 0
        if (s.Count == 0)
            nxt.Add(0);
         
        else
         
            // number of NGEs to right of arr[i] is
            // one greater than the number of NGEs to right
            // of higher number to its right
            nxt.Add(nxt[n - s.Peek() - 1 ] + 1);
         
        s.Push(i);
    }
 
    // reverse again because values are in reverse order
    nxt.Reverse();
 
    // returns the vector of number of next
    // greater elements to the right of each index.
    return nxt;
}
 
// Driver code
public static void Main(String[] args)
{
    int n = 8;
    int []arr = { 3, 4, 2, 7, 5, 8, 10, 6 };
    List nxt = no_NGN(arr, n);
   
    // query 1 answered
    Console.Write(nxt[3] +"\n");
 
    // query 2 answered
    Console.Write(nxt[6] +"\n");
 
    // query 3 answered
    Console.Write(nxt[1] +"\n");
}
}
 
// This code iscontributed by aashish1995

Javascript


输出
2
0
3

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程