每个子数组的两个最大元素之间的明显差异计数
给定一个大小为N的数组arr[] 。任务是计算给定数组大小至少为 2 的每个子数组的两个最大元素之间的唯一差异数。
例子:
Input: arr[] = { 5, 1, 3 }, N = 3
Output: 2
Explanation: The subarrays are {5, 1}, {5, 1, 3}, {1, 3}.
{5, 1} – First max = 5; Second max = 1; difference = (5 – 1) = 4
{5, 1, 3} – First max = 5; Second max = 3; difference = (5 – 3) = 2
{1, 3} – First max = 3; Second max = 1; difference = (3 – 1) = 2
Unique height differences are {4, 2} = 2
Input: arr[] = {5, 2, 3, 8}, N = 4
Output: 4
Explanation: The subarrays are: {5, 2}, {5, 2, 3}, {5, 2, 3, 8}, {2, 3}, {2, 3, 8}, {3, 8}
{5, 2} – First max = 5; Second max = 2; difference = (5 – 2) = 3
{5, 2, 3} – First max = 5; Second max = 3; difference = (5 – 3) = 2
{5, 2, 3, 8} – First max = 8; Second max = 5; difference = (8 – 5) = 3
{2, 3} – First max = 3; Second max = 2; difference = (3 – 2) = 1
{2, 3, 8} – First max = 8; Second max = 3; difference = (8 – 3) = 5
{3,8} – First max = 8; Second max = 3; difference = (8 – 3) = 5
Unique height differences are {3, 2, 1, 5} = 4
方法:根据以下观察可以解决问题。每个子数组只需要第一个和第二个最大值。当另一个最大元素进入子数组时,需要更新最大值。堆栈的概念用于实现这一观察。请按照以下步骤解决此问题。
- 将下一个更大的元素存储在两个数组中每个数组元素的左侧和右侧。
- 找到该索引处的下一个较大元素与该索引处的原始元素之间的差异,以及该索引处的下一个较大元素与该索引处的原始元素之间的差异,并存储在包含唯一值的集合中。
- 打印集合的大小
下面是上述方法的实现。
C++
// C++ code to implement above approach
#include
using namespace std;
// Function to count the number
// of unique differences
int countUnique(vector& arr, int n)
{
// Arrays to store next greater
// to the left and next greater
// to the right for every arr[i]
vector ngl(n, 0);
vector ngr(n, 0);
stack st;
set s;
// Loop to find next greater element
// to the left of arr[i]
ngl[0] = -1;
st.push(arr[0]);
for (int i = 1; i < n; i++) {
while (st.size() > 0 && arr[i] > st.top()) {
st.pop();
}
if (st.size() == 0) {
ngl[i] = -1;
}
else {
ngl[i] = st.top();
}
st.push(arr[i]);
}
while (st.size() > 0) {
st.pop();
}
// Loop to find next greater element
// to the left of arr[i]
ngr[n - 1] = -1;
st.push(arr[n - 1]);
for (int i = n - 2; i >= 0; i--) {
while (st.size() > 0 && arr[i] >= st.top()) {
st.pop();
}
if (st.size() != 0) {
ngr[i] = st.top();
}
else {
ngr[i] = -1;
}
st.push(arr[i]);
}
for (int i = 0; i < n; i++) {
if (ngl[i] != -1) {
s.insert(ngl[i] - arr[i]);
}
if (ngr[i] != -1) {
s.insert(ngr[i] - arr[i]);
}
}
return s.size();
}
// Driver code
int main()
{
int N = 4;
vector arr = { 5, 2, 3, 8 };
cout << (countUnique(arr, N));
return 0;
}
// This code is contributed by rakeshsahni
Java
// Java code to implement above approach
import java.io.*;
import java.util.*;
class GFG {
// Function to count the number
// of unique differences
public static int countUnique(int arr[], int n)
{
// Arrays to store next greater
// to the left and next greater
// to the right for every arr[i]
int[] ngl = new int[n];
int[] ngr = new int[n];
Stack st = new Stack<>();
HashSet s = new HashSet<>();
// Loop to find next greater element
// to the left of arr[i]
ngl[0] = -1;
st.push(arr[0]);
for (int i = 1; i < n; i++) {
while (st.size() > 0 &&
arr[i] > st.peek()) {
st.pop();
}
if (st.size() == 0) {
ngl[i] = -1;
}
else {
ngl[i] = st.peek();
}
st.push(arr[i]);
}
while (st.size() > 0) {
st.pop();
}
// Loop to find next greater element
// to the left of arr[i]
ngr[n - 1] = -1;
st.push(arr[n - 1]);
for (int i = n - 2; i >= 0; i--) {
while (st.size() > 0 &&
arr[i] >= st.peek()) {
st.pop();
}
if (st.size() != 0) {
ngr[i] = st.peek();
}
else {
ngr[i] = -1;
}
st.push(arr[i]);
}
for (int i = 0; i < n; i++) {
if (ngl[i] != -1) {
s.add(ngl[i] - arr[i]);
}
if (ngr[i] != -1) {
s.add(ngr[i] - arr[i]);
}
}
return s.size();
}
// Driver code
public static void main(String[] args)
{
int N = 4;
int arr[] = { 5, 2, 3, 8 };
System.out.println(countUnique(
arr, N));
}
}
Python3
# Python 3 code to implement above approach
# Function to count the number
# of unique differences
def countUnique(arr, n):
# Arrays to store next greater
# to the left and next greater
# to the right for every arr[i]
ngl = [0]*(n)
ngr = [0]*(n)
st = []
s = set([])
# Loop to find next greater element
# to the left of arr[i]
ngl[0] = -1
st.append(arr[0])
for i in range(1, n):
while (len(st) > 0 and arr[i] > st[-1]):
st.pop()
if (len(st) == 0):
ngl[i] = -1
else:
ngl[i] = st[-1]
st.append(arr[i])
while (len(st) > 0):
st.pop()
# Loop to find next greater element
# to the left of arr[i]
ngr[n - 1] = -1
st.append(arr[n - 1])
for i in range(n - 2, -1, -1):
while (len(st) > 0 and arr[i] >= st[-1]):
st.pop()
if (len(st) != 0):
ngr[i] = st[-1]
else:
ngr[i] = -1
st.append(arr[i])
for i in range(n):
if (ngl[i] != -1):
s.add(ngl[i] - arr[i])
if (ngr[i] != -1):
s.add(ngr[i] - arr[i])
return len(s)
# Driver code
if __name__ == "__main__":
N = 4
arr = [5, 2, 3, 8]
print(countUnique(arr, N))
# This code is contributed by ukasp.
C#
// C# code to implement above approach
using System;
using System.Collections.Generic;
class GFG {
// Function to count the number
// of unique differences
public static int countUnique(int[] arr, int n)
{
// Arrays to store next greater
// to the left and next greater
// to the right for every arr[i]
int[] ngl = new int[n];
int[] ngr = new int[n];
Stack st = new Stack();
HashSet s = new HashSet();
// Loop to find next greater element
// to the left of arr[i]
ngl[0] = -1;
st.Push(arr[0]);
for (int i = 1; i < n; i++) {
while (st.Count > 0 &&
arr[i] > st.Peek()) {
st.Pop();
}
if (st.Count == 0) {
ngl[i] = -1;
}
else {
ngl[i] = st.Peek();
}
st.Push(arr[i]);
}
while (st.Count > 0) {
st.Pop();
}
// Loop to find next greater element
// to the left of arr[i]
ngr[n - 1] = -1;
st.Push(arr[n - 1]);
for (int i = n - 2; i >= 0; i--) {
while (st.Count > 0 &&
arr[i] >= st.Peek()) {
st.Pop();
}
if (st.Count != 0) {
ngr[i] = st.Peek();
}
else {
ngr[i] = -1;
}
st.Push(arr[i]);
}
for (int i = 0; i < n; i++) {
if (ngl[i] != -1) {
s.Add(ngl[i] - arr[i]);
}
if (ngr[i] != -1) {
s.Add(ngr[i] - arr[i]);
}
}
return s.Count;
}
// Driver code
public static void Main()
{
int N = 4;
int[] arr = { 5, 2, 3, 8 };
Console.Write(countUnique(arr, N));
}
}
// This code is contributed by saurabh_jaiswal.
Javascript
4
时间复杂度: O(N)
辅助空间: O(N)