Maximum of minimums of every window size in a given array
Given an integer array arr[] of size n, the task is to find the maximum of the minimums for every window size in the given array, where the window size ranges from 1 to n.
Example:
Input: arr[] = [10, 20, 30]
Output: [30, 20, 10]
Explanation:
First element in output indicates maximum of minimums of all windows of size 1. Minimums of windows of size 1 are [10], [20], [30]. Maximum of these minimums are 30 and similarly other outputs can be computedInput: arr[] = [10, 20, 30, 50, 10, 70, 30]
Output: [70, 30, 20, 10, 10, 10, 10]
Explanation: The first element in the output indicates the maximum of minimums of all windows of size 1.
Minimums of windows of size 1 are [10], [20], [30], [50], [10], [70] and [30].
Maximum of these minimums is 70
The second element in the output indicates the maximum of minimums of all windows of size 2.
Minimums of windows of size 2 are [10], [20], [30], [10], [10], and [30].
Maximum of these minimums is 30
The third element in the output indicates the maximum of minimums of all windows of size 3.
Minimums of windows of size 3 are [10], [20], [10], [10] and [10].
Maximum of these minimums is 20
Similarly, other elements of output are computed.
Table of Content
[Naive Approach] – O(n^3) Time and O(1) Space
The idea is to calculate the minimum of every window separately and print the maximum of each window size.
// C++ program to find the maximum of the minimums
// for every window size in the array
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
vector<int> maxOfMins(vector<int>& arr) {
int n = arr.size();
vector<int> res(n, 0);
// Consider all windows of different
// sizes starting from size 1
for (int k = 1; k <= n; k++) {
// Initialize max of min for current window size k
int maxOfMin = INT_MIN;
// Traverse through all windows of current size k
for (int i = 0; i <= n - k; i++) {
// Find minimum of current window
int minVal = arr[i];
for (int j = 1; j < k; j++) {
if (arr[i + j] < minVal)
minVal = arr[i + j];
}
// Update maxOfMin if required
if (minVal > maxOfMin)
maxOfMin = minVal;
}
// Store max of min for current window size
res[k - 1] = maxOfMin;
}
return res;
}
int main() {
vector<int> arr = { 10, 20, 30, 50, 10, 70, 30 };
vector<int> res = maxOfMins(arr);
for (int x : res)
cout << x << " ";
return 0;
}
// C program to find the maximum of the minimums
// for every window size in the array
#include <stdio.h>
#include <limits.h>
void maxOfMins(int arr[], int n, int res[]) {
// Consider all windows of different sizes
// starting from size 1
for (int k = 1; k <= n; k++) {
// Initialize max of min for current window size k
int maxOfMin = INT_MIN;
// Traverse through all windows of current size k
for (int i = 0; i <= n - k; i++) {
// Find minimum of current window
int minVal = arr[i];
for (int j = 1; j < k; j++) {
if (arr[i + j] < minVal) {
minVal = arr[i + j];
}
}
// Update maxOfMin if required
if (minVal > maxOfMin) {
maxOfMin = minVal;
}
}
// Store max of min for current window size
res[k - 1] = maxOfMin;
}
}
int main() {
int arr[] = {10, 20, 30, 50, 10, 70, 30};
int n = sizeof(arr) / sizeof(arr[0]);
int res[n];
maxOfMins(arr, n, res);
for (int i = 0; i < n; i++) {
printf("%d ", res[i]);
}
return 0;
}
// Java program to find the maximum of the minimums
// for every window size in the array
import java.util.*;
class GfG {
static ArrayList<Integer> maxOfMins(int[] arr) {
int n = arr.length;
ArrayList<Integer> res = new ArrayList<>(Collections.nCopies(n, 0));
// Consider all windows of different
// sizes starting from size 1
for (int k = 1; k <= n; k++) {
// Initialize max of min for current window size k
int maxOfMin = Integer.MIN_VALUE;
// Traverse through all windows of current size k
for (int i = 0; i <= n - k; i++) {
// Find minimum of current window
int minVal = arr[i];
for (int j = 1; j < k; j++) {
if (arr[i + j] < minVal)
minVal = arr[i + j];
}
// Update maxOfMin if required
if (minVal > maxOfMin)
maxOfMin = minVal;
}
// Store max of min for current window size
res.set(k - 1, maxOfMin);
}
return res;
}
public static void main(String[] args) {
int[] arr = {10, 20, 30, 50, 10, 70, 30};
ArrayList<Integer> res = maxOfMins(arr);
for (int x : res)
System.out.print(x + " ");
}
}
# Python program to find the maximum of the minimums
# for every window size in the array
def maxOfMins(arr):
n = len(arr)
res = [0] * n
# Consider all windows of different
# sizes starting from size 1
for k in range(1, n + 1):
# Initialize max of min for current window size k
maxOfMin = float('-inf')
# Traverse through all windows of current size k
for i in range(n - k + 1):
# Find minimum of current window
minVal = arr[i]
for j in range(1, k):
minVal = min(minVal, arr[i + j])
# Update maxOfMin if required
maxOfMin = max(maxOfMin, minVal)
# Store max of min for current window size
res[k - 1] = maxOfMin
return res
if __name__ == "__main__":
arr = [10, 20, 30, 50, 10, 70, 30]
res = maxOfMins(arr)
print(' '.join(map(str, res)))
// C# program to find the maximum of the minimums
// for every window size in the array
using System;
using System.Collections.Generic;
class GfG {
static List<int> maxOfMins(int[] arr) {
int n = arr.Length;
List<int> res = new List<int>(new int[n]);
// Consider all windows of different
// sizes starting from size 1
for (int k = 1; k <= n; k++) {
// Initialize max of min for current window size k
int maxOfMin = int.MinValue;
// Traverse through all windows of current size k
for (int i = 0; i <= n - k; i++) {
// Find minimum of current window
int minVal = arr[i];
for (int j = 1; j < k; j++) {
if (arr[i + j] < minVal)
minVal = arr[i + j];
}
// Update maxOfMin if required
if (minVal > maxOfMin)
maxOfMin = minVal;
}
// Store max of min for current window size
res[k - 1] = maxOfMin;
}
return res;
}
static void Main() {
int[] arr = {10, 20, 30, 50, 10, 70, 30};
List<int> res = maxOfMins(arr);
Console.WriteLine(string.Join(" ", res));
}
}
// JavaScript program to find the maximum of the minimums
// for every window size in the array
function maxOfMins(arr) {
const n = arr.length;
const res = new Array(n).fill(0);
// Consider all windows of different sizes starting from size 1
for (let k = 1; k <= n; k++) {
// Initialize max of min for current window size k
let maxOfMin = -Infinity;
// Traverse through all windows of current size k
for (let i = 0; i <= n - k; i++) {
// Find minimum of current window
let minVal = arr[i];
for (let j = 1; j < k; j++) {
minVal = Math.min(minVal, arr[i + j]);
}
// Update maxOfMin if required
maxOfMin = Math.max(maxOfMin, minVal);
}
// Store max of min for current window size
res[k - 1] = maxOfMin;
}
return res;
}
// Driver program
const arr = [10, 20, 30, 50, 10, 70, 30];
const res = maxOfMins(arr);
console.log(res.join(" "));
Output
70 30 20 10 10 10 10
[Expected Approach] Using Stack – O(n) Time and O(n) Space
The idea is to find the next smaller and previous smaller of each element and update the maximum of window with size as the difference in their indices. This problem is mainly a variation of Largest Area in a Histogram.
Below is the implementation of the above approach:
- Initialize
res[]
to store maximum minimums andlen[]
to store window sizes. Use a stacks
for efficient processing. - Traverse the array to determine window sizes. For each element, pop larger or equal elements from the stack, calculate their window sizes, and update
len[]
. Push the current index onto the stack. - Process remaining stack elements to determine their window sizes using the right boundary.
- Populate
res[]
usinglen[]
andarr[]
, storing the maximum minimum for each window size. - Update
res[]
to ensure values correctly reflect the maximum of the minimums. - Return
res[]
, containing the maximum of minimums for every window size.
// C++ program to find the maximum of the minimums
// for every window size in the array
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
vector<int> maxOfMins(vector<int>& arr) {
int n = arr.size();
vector<int> res(n, 0);
stack<int> s;
// Array to store the length of the window
// where each element is the minimum
vector<int> len(n, 0);
// Traverse through array to determine
// window sizes using a stack
for (int i = 0; i < n; i++) {
// Process elements to find next smaller
// element on the left
while (!s.empty() && arr[s.top()] >= arr[i]) {
int top = s.top();
s.pop();
int windowSize = s.empty() ? i : i - s.top() - 1;
len[top] = windowSize;
}
s.push(i);
}
// Process remaining elements in the stack
// for right boundaries
while (!s.empty()) {
int top = s.top();
s.pop();
int windowSize = s.empty() ? n : n - s.top() - 1;
len[top] = windowSize;
}
// Fill res[] based on len[] and arr[]
for (int i = 0; i < n; i++) {
int windowSize = len[i] - 1; // 0-based indexing
res[windowSize] = max(res[windowSize], arr[i]);
}
// Fill remaining entries in res[] to ensure
// all are max of min
for (int i = n - 2; i >= 0; i--)
res[i] = max(res[i], res[i + 1]);
return res;
}
int main() {
vector<int> arr = { 10, 20, 30, 50, 10, 70, 30 };
vector<int> res = maxOfMins(arr);
for (int x : res)
cout << x << " ";
return 0;
}
// Java program to find the maximum of the minimums
// for every window size in the array
import java.util.*;
class GfG {
static ArrayList<Integer> maxOfMins(int[] arr) {
int n = arr.length;
ArrayList<Integer> res = new ArrayList<>(Collections.nCopies(n, 0));
Stack<Integer> s = new Stack<>();
// Array to store the length of the window
// where each element is the minimum
ArrayList<Integer> lenArr = new ArrayList<>(Collections.nCopies(n, 0));
// Traverse through array to determine
// window sizes using a stack
for (int i = 0; i < n; i++) {
// Process elements to find next smaller
// element on the left
while (!s.isEmpty() && arr[s.peek()] >= arr[i]) {
int top = s.pop();
int windowSize = s.isEmpty() ? i : i - s.peek() - 1;
lenArr.set(top, windowSize);
}
s.push(i);
}
// Process remaining elements in the stack
// for right boundaries
while (!s.isEmpty()) {
int top = s.pop();
int windowSize = s.isEmpty() ? n : n - s.peek() - 1;
lenArr.set(top, windowSize);
}
// Fill ressult based on lenArr[] and arr[]
for (int i = 0; i < n; i++) {
int windowSize = lenArr.get(i) - 1; // 0-based indexing
res.set(windowSize, Math.max(res.get(windowSize), arr[i]));
}
// Fill remaining entries in res[] to ensure
// all are max of min
for (int i = n - 2; i >= 0; i--)
res.set(i, Math.max(res.get(i), res.get(i + 1)));
return res;
}
public static void main(String[] args) {
int[] arr = {10, 20, 30, 50, 10, 70, 30};
ArrayList<Integer> res = maxOfMins(arr);
for (int x : res)
System.out.print(x + " ");
}
}
# Python program to find the maximum of the minimums
# for every window size in the array
def maxOfMins(arr):
n = len(arr)
res = [0] * n
s = []
# Array to store the length of the window
# where each element is the minimum
lenArr = [0] * n
# Traverse through array to determine
# window sizes using a stack
for i in range(n):
# Process elements to find next smaller
# element on the left
while s and arr[s[-1]] >= arr[i]:
top = s.pop()
windowSize = i if not s else i - s[-1] - 1
lenArr[top] = windowSize
s.append(i)
# Process remaining elements in the stack
# for right boundaries
while s:
top = s.pop()
windowSize = n if not s else n - s[-1] - 1
lenArr[top] = windowSize
# Fill res[] based on len_arr[] and arr[]
for i in range(n):
windowSize = lenArr[i] - 1 # 0-based indexing
res[windowSize] = max(res[windowSize], arr[i])
# Fill remaining entries in res[] to ensure
# all are max of min
for i in range(n - 2, -1, -1):
res[i] = max(res[i], res[i + 1])
return res
if __name__ == '__main__':
arr = [10, 20, 30, 50, 10, 70, 30]
res = maxOfMins(arr)
print(' '.join(map(str, res)))
using System;
using System.Collections.Generic;
class GfG {
static List<int> maxOfMins(int[] arr) {
int n = arr.Length;
List<int> res = new List<int>(new int[n]);
Stack<int> s = new Stack<int>();
// Array to store the length of the window where each element is the minimum
List<int> lenArr = new List<int>(new int[n]);
// Traverse through array to determine
// window sizes using a stack
for (int i = 0; i < n; i++) {
// Process elements to find next smaller
// element on the left
while (s.Count > 0 && arr[s.Peek()] >= arr[i]) {
int top = s.Pop();
int windowSize = s.Count == 0 ? i : i - s.Peek() - 1;
lenArr[top] = windowSize;
}
s.Push(i);
}
// Process remaining elements in the stack
// for right boundaries
while (s.Count > 0) {
int top = s.Pop();
int windowSize = s.Count == 0 ? n : n - s.Peek() - 1;
lenArr[top] = windowSize;
}
// Fill res[] based on lenArr[] and arr[]
for (int i = 0; i < n; i++) {
int windowSize = lenArr[i] - 1; // 0-based indexing
if (windowSize >= 0 && windowSize < n) // Prevent out-of-bounds access
res[windowSize] = Math.Max(res[windowSize], arr[i]);
}
// Fill remaining entries in res[] to ensure
// all are max of min
for (int i = n - 2; i >= 0; i--) {
res[i] = Math.Max(res[i], res[i + 1]);
}
return res;
}
static void Main() {
int[] arr = {10, 20, 30, 50, 10, 70, 30};
List<int> res = maxOfMins(arr);
Console.WriteLine(string.Join(" ", res));
}
}
// JavaScript program to find the maximum of the minimums
// for every window size in the array
function maxOfMins(arr) {
let n = arr.length;
let res = new Array(n).fill(0);
let s = [];
// Array to store the length of the window
// where each element is the minimum
let len = new Array(n).fill(0);
// Traverse through array to determine
// window sizes using a stack
for (let i = 0; i < n; i++) {
// Process elements to find next smaller
// element on the left
while (s.length > 0 && arr[s[s.length - 1]] >= arr[i]) {
let top = s.pop();
let windowSize = s.length === 0 ? i : i - s[s.length - 1] - 1;
len[top] = windowSize;
}
s.push(i);
}
// Process remaining elements in the stack
// for right boundaries
while (s.length > 0) {
let top = s.pop();
let windowSize = s.length === 0 ? n : n - s[s.length - 1] - 1;
len[top] = windowSize;
}
// Fill res[] based on len[] and arr[]
for (let i = 0; i < n; i++) {
let windowSize = len[i] - 1; // 0-based indexing
res[windowSize] = Math.max(res[windowSize], arr[i]);
}
// Fill remaining entries in res[] to ensure
// all are max of min
for (let i = n - 2; i >= 0; i--) {
res[i] = Math.max(res[i], res[i + 1]);
}
return res;
}
// Driver program
const arr = [10, 20, 30, 50, 10, 70, 30];
const res = maxOfMins(arr);
console.log(res.join(' '));
Output
70 30 20 10 10 10 10