Array 中每个索引的最大范围子数组,使得 A[i] = min(A[L], A[L+1], ... A[R])
给定一个包含N个不同整数的数组arr[] ,任务是为每个索引i (1≤i≤N)计算一个范围[L, R]使得arr[i] = min(arr[L], arr[ L+1], … arr[R]) ,其中L≤i≤R且RL最大化。
例子:
Input: N = 3, arr[] = {1, 3, 2}
Output: 1 3
2 2
2 3
Explanation: 1 is minimum in the range [1, 3]
3 is minimum in the range [2, 2]
2 is minimum in range [2, 3]
Input: N = 3, arr[] = {4, 5, 6}
Output: 1 3
2 3
3 3
方法:可以观察到 每个索引都需要前一个较小的元素和下一个较小的元素来计算所需的范围。这个想法是使用堆栈来查找前一个更大和下一个更大的元素。请按照以下步骤解决问题:
- 创建两个数组L[]和R[] ,分别存储当前元素左侧最近的较小元素和右侧最近的较小元素。
- 创建一个堆栈S ,并添加其中第一个元素的索引。
- 遍历给定的数组arr[] ,并弹出栈,直到栈顶, S不小于当前元素。
- 现在将左边最近的较小元素,即L[i]设置为S的顶部,如果S为空,则将其设置为 0。将当前元素推入S 。
- 同样,从末端以相反的方向遍历并按照相同的步骤填充数组R[] 。
- 在[1, N]范围内迭代并为每个索引i打印L[i]和R[i] 。
以下是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to print the range for each index
void rangeFinder(int arr[], int N)
{
// Array to store index of closest smaller
// element at left sub-array
int L[N];
// Array to store index of closest smaller
// element at right sub-array
int R[N];
// Stack to find previous smaller element
stack S;
// Since there is no element before first
// element, so set L[0]=0
L[0] = 0;
// Push the first element index in stack
S.push(0);
// Traverse the array, arr[]
for (int i = 1; i < N; i++) {
// Pop until the top of stack is greater
// than current element
while (!S.empty() && arr[S.top()] > arr[i])
S.pop();
// Update L[i] as peek as it is
// previous smaller element
if (!S.empty())
L[i] = S.top() + 1;
// Otherwise, update L[i] to 0
else
L[i] = 0;
// Push the current index
S.push(i);
}
// Empty the stack, S
while (!S.empty())
S.pop();
// Since there is no element after
// last element, so set R[N-1]=N-1
R[N - 1] = N - 1;
// Push the last element index into stack
S.push(N - 1);
// Traverse the array from the end
for (int i = N - 2; i >= 0; i--) {
// Pop until the top of S is greater
// than current element
while (!S.empty() && arr[S.top()] > arr[i])
S.pop();
// Set R[i] as top as it is previous
// smaller element from end
if (!S.empty())
R[i] = S.top() - 1;
// Otherwise, update R[i] as N-1
else
R[i] = N - 1;
// Push the current index
S.push(i);
}
// Print the required range using L and R array
for (int i = 0; i < N; i++) {
cout << L[i] + 1 << " " << R[i] + 1 << endl;
}
}
// Driver Code
int main()
{
// Given Input
int arr[] = { 1, 3, 2 };
int N = sizeof(arr) / sizeof(arr[0]);
// Function Call
rangeFinder(arr, N);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
import java.util.*;
class GFG{
// Function to print the range for each index
static void rangeFinder(int arr[], int N)
{
// Array to store index of closest smaller
// element at left sub-array
int[] L = new int[N];
// Array to store index of closest smaller
// element at right sub-array
int[] R = new int[N];
// Stack to find previous smaller element
Stack S = new Stack();
// Since there is no element before first
// element, so set L[0]=0
L[0] = 0;
// Push the first element index in stack
S.push(0);
// Traverse the array, arr[]
for(int i = 1; i < N; i++)
{
// Pop until the top of stack is greater
// than current element
while (!S.empty() && arr[S.peek()] > arr[i])
S.pop();
// Update L[i] as peek as it is
// previous smaller element
if (!S.empty())
L[i] = S.peek() + 1;
// Otherwise, update L[i] to 0
else
L[i] = 0;
// Push the current index
S.push(i);
}
// Empty the stack, S
while (!S.empty())
S.pop();
// Since there is no element after
// last element, so set R[N-1]=N-1
R[N - 1] = N - 1;
// Push the last element index into stack
S.push(N - 1);
// Traverse the array from the end
for(int i = N - 2; i >= 0; i--)
{
// Pop until the top of S is greater
// than current element
while (!S.empty() && arr[S.peek()] > arr[i])
S.pop();
// Set R[i] as top as it is previous
// smaller element from end
if (!S.empty())
R[i] = S.peek() - 1;
// Otherwise, update R[i] as N-1
else
R[i] = N - 1;
// Push the current index
S.push(i);
}
// Print the required range using L and R array
for(int i = 0; i < N; i++)
{
System.out.println((L[i] + 1) + " " +
(R[i] + 1));
}
}
// Driver Code
public static void main(String[] args)
{
// Given Input
int arr[] = { 1, 3, 2 };
int N = arr.length;
// Function Call
rangeFinder(arr, N);
}
}
// This code is contributed by MuskanKalra1
Python3
# Python3 program for the above approach
# Function to print the range for each index
def rangeFinder(arr, N):
# Array to store index of closest smaller
# element at left sub-array
L = [0 for i in range(N)]
# Array to store index of closest smaller
# element at right sub-array
R = [0 for i in range(N)]
# Stack to find previous smaller element
S = []
# Since there is no element before first
# element, so set L[0]=0
L[0] = 0
# Push the first element index in stack
S.append(0)
# Traverse the array, arr[]
for i in range(1, N, 1):
# Pop until the top of stack is greater
# than current element
while (len(S) > 0 and
arr[S[len(S) - 1]] > arr[i]):
S = S[:-1]
# Update L[i] as peek as it is
# previous smaller element
if (len(S) > 0):
L[i] = S[len(S) - 1] + 1
# Otherwise, update L[i] to 0
else:
L[i] = 0
# Push the current index
S.append(i)
# Empty the stack, S
while (len(S) > 0):
S.pop()
# Since there is no element after
# last element, so set R[N-1]=N-1
R[N - 1] = N - 1
# Push the last element index into stack
S.append(N - 1)
# Traverse the array from the end
i = N - 2
while (i >= 0):
# Pop until the top of S is greater
# than current element
while (len(S) > 0 and
arr[S[len(S) - 1]] > arr[i]):
S = S[:-1]
# Set R[i] as top as it is previous
# smaller element from end
if (len(S) > 0):
R[i] = S[len(S) - 1] - 1;
# Otherwise, update R[i] as N-1
else:
R[i] = N - 1
# Push the current index
S.append(i)
i -= 1
# Print the required range using L and R array
for i in range(N):
print(L[i] + 1, R[i] + 1)
# Driver Code
if __name__ == '__main__':
# Given Input
arr = [ 1, 3, 2 ]
N = len(arr)
# Function Call
rangeFinder(arr, N)
# This code is contributed by ipg2016107
C#
// C# program for the above approach
using System;
using System.Collections;
class GFG {
// Function to print the range for each index
static void rangeFinder(int[] arr, int N)
{
// Array to store index of closest smaller
// element at left sub-array
int[] L = new int[N];
// Array to store index of closest smaller
// element at right sub-array
int[] R = new int[N];
// Stack to find previous smaller element
Stack S = new Stack();
// Since there is no element before first
// element, so set L[0]=0
L[0] = 0;
// Push the first element index in stack
S.Push(0);
// Traverse the array, arr[]
for(int i = 1; i < N; i++)
{
// Pop until the top of stack is greater
// than current element
while (S.Count > 0 && arr[(int)S.Peek()] > arr[i])
S.Pop();
// Update L[i] as peek as it is
// previous smaller element
if (S.Count > 0)
L[i] = (int)S.Peek() + 1;
// Otherwise, update L[i] to 0
else
L[i] = 0;
// Push the current index
S.Push(i);
}
// Empty the stack, S
while (S.Count > 0)
S.Pop();
// Since there is no element after
// last element, so set R[N-1]=N-1
R[N - 1] = N - 1;
// Push the last element index into stack
S.Push(N - 1);
// Traverse the array from the end
for(int i = N - 2; i >= 0; i--)
{
// Pop until the top of S is greater
// than current element
while (S.Count > 0 && arr[(int)S.Peek()] > arr[i])
S.Pop();
// Set R[i] as top as it is previous
// smaller element from end
if (S.Count > 0)
R[i] = (int)S.Peek() - 1;
// Otherwise, update R[i] as N-1
else
R[i] = N - 1;
// Push the current index
S.Push(i);
}
// Print the required range using L and R array
for(int i = 0; i < N; i++)
{
Console.WriteLine((L[i] + 1) + " " + (R[i] + 1));
}
}
static void Main()
{
// Given Input
int[] arr = { 1, 3, 2 };
int N = arr.Length;
// Function Call
rangeFinder(arr, N);
}
}
// This code is contributed by divyesh072019.
Javascript
输出:
1 3
2 2
2 3
时间复杂度: O(N)
辅助空间: O(N)