给定一个包含 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 现场工作专业课程和学生竞争性编程现场课程。