计算第二高在最高之前的子数组
给定一个包含至少大小为 2 的N个不同元素的数组。数组中的一对 (a, b) 定义为“a”是第二高元素的索引,“b”是数组中最高元素的索引。任务是计算所有子数组中 a < b 的所有不同对。
例子 :
Input : arr[] = { 1, 3, 2, 4 }
Output : 3
解释 :
子数组 { 1 }, { 3 }, { 2 }, { 4 } 不包含任何这样的对
子数组 { 1, 3 }, { 2, 4 } 包含 (1, 2) 作为对
子数组 { 3, 2 } 不包含任何这样的对
子数组 { 3, 2, 4 } 包含 (1, 3) 作为一对
子数组 { 1, 3, 2 } 不包含任何这样的对
子数组 { 1, 3, 2, 4 } 包含 (2, 4) 作为一对
因此,有 3 个不同的对,它们是 (1, 2)、(1, 3) 和 (2, 4)。
方法1:(蛮力)——简单的方法可以,
1. 找到所有子数组。
2. 对于每个子数组,找到第二大和最大的元素。
3. 检查第二大元素是否位于最大元素之前。
4. 如果是,请检查该索引对是否已被计算在内。如果不存储该对并将计数加 1,否则忽略。
时间复杂度: O(n 2 )。
方法2:(使用堆栈)-
对于给定的数组 A,假设索引为curr (A[curr]) 处的元素,第一个大于它的元素,在它之后是 A[next],第一个元素大于它,在它之前是 A[prev]。观察到所有从 [prev + 1, curr] 范围内的任何索引开始到索引 next 结束的所有子数组,A[curr] 是第二大的,A[next] 是最大的,它们生成 (curr – prev + 1)最大和第二个最大值的差异为 (next – curr + 1)。
如果我们在数组中获得下一个和上一个更大的元素,并跟踪任何差异(最大和第二大)可能的最大对数。我们将需要添加所有这些数字。
现在剩下的唯一工作就是获得更大的元素(之后和之前)任何元素。为此,请参阅下一个更大的元素。
从数组中的起始元素开始遍历,以降序跟踪堆栈中的所有数字。到达任意数字后,从堆栈中弹出所有小于当前元素的元素,以获取大于它的数字的位置并将当前元素压入其上。这将为数组中的所有数字生成所需的值。
C++
// C++ program to count number of distinct instance
// where second highest number lie
// before highest number in all subarrays.
#include
#define MAXN 100005
using namespace std;
// Finding the next greater element of the array.
void makeNext(int arr[], int n, int nextBig[])
{
stack > s;
for (int i = n - 1; i >= 0; i--) {
nextBig[i] = i;
while (!s.empty() && s.top().first < arr[i])
s.pop();
if (!s.empty())
nextBig[i] = s.top().second;
s.push(pair(arr[i], i));
}
}
// Finding the previous greater element of the array.
void makePrev(int arr[], int n, int prevBig[])
{
stack > s;
for (int i = 0; i < n; i++) {
prevBig[i] = -1;
while (!s.empty() && s.top().first < arr[i])
s.pop();
if (!s.empty())
prevBig[i] = s.top().second;
s.push(pair(arr[i], i));
}
}
// Wrapper Function
int wrapper(int arr[], int n)
{
int nextBig[MAXN];
int prevBig[MAXN];
int maxi[MAXN];
int ans = 0;
// Finding previous largest element
makePrev(arr, n, prevBig);
// Finding next largest element
makeNext(arr, n, nextBig);
for (int i = 0; i < n; i++)
if (nextBig[i] != i)
maxi[nextBig[i] - i] = max(maxi[nextBig[i] - i],
i - prevBig[i]);
for (int i = 0; i < n; i++)
ans += maxi[i];
return ans;
}
// Driven Program
int main()
{
int arr[] = { 1, 3, 2, 4 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << wrapper(arr, n) << endl;
return 0;
}
Java
// Java program to count number of distinct instance
// where second highest number lie
// before highest number in all subarrays.
import java.util.*;
class GFG
{
static int MAXN = 100005;
static class pair
{
int first, second;
public pair(int first, int second)
{
this.first = first;
this.second = second;
}
}
// Finding the next greater element of the array.
static void makeNext(int arr[], int n, int nextBig[])
{
Stack s = new Stack<>();
for (int i = n - 1; i >= 0; i--)
{
nextBig[i] = i;
while (!s.empty() && s.peek().first < arr[i])
s.pop();
if (!s.empty())
nextBig[i] = s.peek().second;
s.push(new pair(arr[i], i));
}
}
// Finding the previous greater element of the array.
static void makePrev(int arr[], int n, int prevBig[])
{
Stack s = new Stack<>();
for (int i = 0; i < n; i++)
{
prevBig[i] = -1;
while (!s.empty() && s.peek().first < arr[i])
s.pop();
if (!s.empty())
prevBig[i] = s.peek().second;
s.push(new pair(arr[i], i));
}
}
// Wrapper Function
static int wrapper(int arr[], int n)
{
int []nextBig = new int[MAXN];
int []prevBig = new int[MAXN];
int []maxi = new int[MAXN];
int ans = 0;
// Finding previous largest element
makePrev(arr, n, prevBig);
// Finding next largest element
makeNext(arr, n, nextBig);
for (int i = 0; i < n; i++)
if (nextBig[i] != i)
maxi[nextBig[i] - i] = Math.max(maxi[nextBig[i] - i],
i - prevBig[i]);
for (int i = 0; i < n; i++)
ans += maxi[i];
return ans;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 1, 3, 2, 4 };
int n = arr.length;
System.out.println(wrapper(arr, n));
}
}
// This code is contributed by Princi Singh
Python3
# Python3 program to count number of distinct
# instance where second highest number lie
# before highest number in all subarrays.
from typing import List
MAXN = 100005
# Finding the next greater element
# of the array.
def makeNext(arr: List[int], n: int,
nextBig: List[int]) -> None:
# Stack
s = []
for i in range(n - 1, -1, -1):
nextBig[i] = i
while len(s) and s[-1][0] < arr[i]:
s.pop()
if len(s):
nextBig[i] = s[-1][1]
s.append((arr[i], i))
# Finding the previous greater
# element of the array.
def makePrev(arr: List[int], n: int,
prevBig: List[int]) -> None:
# Stack
s = []
for i in range(n):
prevBig[i] = -1
while (len(s) and s[-1][0] < arr[i]):
s.pop()
if (len(s)):
prevBig[i] = s[-1][1]
s.append((arr[i], i))
# Wrapper Function
def wrapper(arr: List[int], n: int) -> int:
nextBig = [0] * MAXN
prevBig = [0] * MAXN
maxi = [0] * MAXN
ans = 0
# Finding previous largest element
makePrev(arr, n, prevBig)
# Finding next largest element
makeNext(arr, n, nextBig)
for i in range(n):
if (nextBig[i] != i):
maxi[nextBig[i] - i] = max(
maxi[nextBig[i] - i],
i - prevBig[i])
for i in range(n):
ans += maxi[i]
return ans
# Driver Code
if __name__ == "__main__":
arr = [ 1, 3, 2, 4 ]
n = len(arr)
print(wrapper(arr, n))
# This code is contributed by sanjeev2552
C#
// C# program to count number of distinct instance
// where second highest number lie
// before highest number in all subarrays.
using System;
using System.Collections.Generic;
class GFG
{
static int MAXN = 100005;
public class pair
{
public int first, second;
public pair(int first, int second)
{
this.first = first;
this.second = second;
}
}
// Finding the next greater element of the array.
static void makeNext(int []arr, int n, int []nextBig)
{
Stack s = new Stack();
for (int i = n - 1; i >= 0; i--)
{
nextBig[i] = i;
while (s.Count!=0 && s.Peek().first < arr[i])
s.Pop();
if (s.Count!=0)
nextBig[i] = s.Peek().second;
s.Push(new pair(arr[i], i));
}
}
// Finding the previous greater element of the array.
static void makePrev(int []arr, int n, int[] prevBig)
{
Stack s = new Stack();
for (int i = 0; i < n; i++)
{
prevBig[i] = -1;
while (s.Count!=0 && s.Peek().first < arr[i])
s.Pop();
if (s.Count!=0)
prevBig[i] = s.Peek().second;
s.Push(new pair(arr[i], i));
}
}
// Wrapper Function
static int wrapper(int []arr, int n)
{
int []nextBig = new int[MAXN];
int []prevBig = new int[MAXN];
int []maxi = new int[MAXN];
int ans = 0;
// Finding previous largest element
makePrev(arr, n, prevBig);
// Finding next largest element
makeNext(arr, n, nextBig);
for (int i = 0; i < n; i++)
if (nextBig[i] != i)
maxi[nextBig[i] - i] = Math.Max(maxi[nextBig[i] - i],
i - prevBig[i]);
for (int i = 0; i < n; i++)
ans += maxi[i];
return ans;
}
// Driver code
public static void Main(String[] args)
{
int[] arr = { 1, 3, 2, 4 };
int n = arr.Length;
Console.WriteLine(wrapper(arr, n));
}
}
// This code is contributed by 29AjayKumar
Javascript
输出 :
3
时间复杂度: O(n)