Open In App

Max of Mins for All Window Sizes

Last Updated : 16 Sep, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an integer array arr[], find the maximum of minimums for every window size from 1 to n. For each window size k, consider all contiguous subarrays of length k and determine the minimum element in each subarray. Among these minimum values, take the maximum one.

Example:

Input: arr[] = [10, 20, 30]
Output: [30, 20, 10]
Explanation: The maximum of minimums for every possible window size.
Window size 1: minimums of [10], [20], [30], maximum of minimums is 30.
Window size 2: minimums of [10, 20],[20,30] maximum of minimums is 20.
Window size 3:minimums of [10,20,30], maximum of minimums is 10.

Input: arr[] = [10, 20, 30, 50, 10, 70, 30]
Output: [70, 30, 20, 10, 10, 10, 10]
Explanation:
Window size 1: minimums are [10, 20, 30, 50, 10, 70, 30], maximum of minimums is 70.
Window size 2: minimums are [10, 20, 30, 10, 10, 30], maximum of minimums is 30.
Window size 3: minimums are [10, 20, 10, 10, 10], maximum of minimums is 20.
Window size 4–7: minimums are [10, 10, 10, 10], maximum of minimums is 10.

[Naive Approach] By Checking All Subarrays O(n3) Time and O(1) Space

The idea is to compute the minimum of every possible window, For each window size from 1 to n and find the maximum of those minimums.

C++
#include <iostream>
#include <vector>
#include <climits>
using namespace std;

vector<int> maxOfMin(vector<int>& arr) {
    int n = arr.size();
    vector<int> res(n);
    
    // for each window size k
    for (int k = 1; k <= n; k++) {
        int maxMin = INT_MIN;
        
        // slide window of size k
        
        for (int i = 0; i <= n - k; i++) {
            int minval = INT_MAX;
            
            // find minimum in current window
            for (int j = i; j < i + k; j++) {
                minval = min(minval, arr[j]);
            }
            
            maxMin = max(maxMin, minval);
        }
        res[k - 1] = maxMin;
    }
    return res;
}


int main() {
    vector<int> arr = {10, 20, 30, 50, 10, 70, 30};
    vector<int> res = maxOfMin(arr);
    for (int val : res) cout << val << " ";
    cout << endl;
    return 0;
}
Java
import java.util.ArrayList;

public class GfG {
    public static ArrayList<Integer> maxOfMin(int[] arr) {
        int n = arr.length;
        ArrayList<Integer> res = new ArrayList<>(n);

        for (int i = 0; i < n; i++) {
            res.add(0);
        }
        
        // For each window size k
        for (int k = 1; k <= n; k++) {
            int maxMin = Integer.MIN_VALUE;
        
            // Slide window of size k
            for (int i = 0; i <= n - k; i++) {
                int minVal = Integer.MAX_VALUE;
            
                // Find minimum in current window
                for (int j = i; j < i + k; j++) {
                    minVal = Math.min(minVal, arr[j]);
                }
                maxMin = Math.max(maxMin, minVal);
            }
            res.set(k - 1, maxMin);
        }
        return res;
    }

    public static void main(String[] args) {
        int[] arr = {10, 20, 30, 50, 10, 70, 30};
        int n = arr.length;
        
        ArrayList<Integer> res = maxOfMin(arr);
        
        for (int val : res) {
            System.out.print(val + " ");
        }
        System.out.println();
    }
}
Python
def maxOfMin(arr):
    n = len(arr)
    res = [0] * n
    
    # For each window size k
    for k in range(1, n + 1):
        maxMin = float('-inf')
        
        # Slide window of size k
        for i in range(n - k + 1):
            minval = float('inf') 
            
            # Find minimum in current window
            for j in range(i, i + k):
                minval = min(minval, arr[j])
            maxMin = max(maxMin, minval)
            
        # Store result for window size k
        res[k - 1] = maxMin 
    return res

if __name__ == "__main__":
    arr = [10, 20, 30, 50, 10, 70, 30]
    n = len(arr)
    
    res = maxOfMin(arr)
    
    print(" ".join(map(str, res)))
C#
using System;
using System.Collections.Generic;

class GfG {
    public static List<int> maxOfMin(int[] arr) {
        int n = arr.Length;
        List<int> res = new List<int>(new int[n]);
        
        // for each window size k
        for (int k = 1; k <= n; k++) {
            int maxMin = int.MinValue;
            
            // slide window of size k
            for (int i = 0; i <= n - k; i++) {
                int minVal = int.MaxValue;
                
                // find minimum in current window
                for (int j = i; j < i + k; j++) {
                    minVal = Math.Min(minVal, arr[j]);
                }
                maxMin = Math.Max(maxMin, minVal);
            }
            res[k - 1] = maxMin; 
        }
        return res;
    }

    public static void Main(string[] args) {
        int[] arr = { 10, 20, 30, 50, 10, 70, 30 };
        int n = arr.Length;

        List<int> res = maxOfMin(arr);

        Console.Write(string.Join(" ", res));
        Console.WriteLine();
    }
}
JavaScript
function maxOfMin(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++) {
    
        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 = maxOfMin(arr);
console.log(res.join(" "));

Output
70 30 20 10 10 10 10 

[Better Approach] Sliding Window Minimum using Deque - O(n2) Time and O(n) Space

The idea is to use the sliding window minimum technique (with a deque) to efficiently find the minimum element of every subarray of size k. By doing this for each window size k = 1 … n, we can compute the maximum of these minimums.

C++
#include <iostream>
#include <vector>
#include <deque>
#include <climits>
using namespace std;

vector<int> maxOfMin(vector<int>& arr) {
    int n = arr.size();
    vector<int> res(n);

    // iterate over all window sizes
    for (int k = 1; k <= n; k++) {
        deque<int> dq;
        int maxMin = INT_MIN;

        // process first k elements
        for (int i = 0; i < k; i++) {
            while (!dq.empty() && arr[i] <= arr[dq.back()])
                dq.pop_back();
            dq.push_back(i);
        }

        // slide the window
        for (int i = k; i < n; i++) {
            maxMin = max(maxMin, arr[dq.front()]);

            while (!dq.empty() && dq.front() <= i - k)
                dq.pop_front();
            while (!dq.empty() && arr[i] <= arr[dq.back()])
                dq.pop_back();

            dq.push_back(i);
        }

        maxMin = max(maxMin, arr[dq.front()]);
        res[k - 1] = maxMin;
    }

    return res;
}

int main() {
    vector<int> arr = {10, 20, 30, 50, 10, 70, 30};
    vector<int> res = maxOfMin(arr);

    for (int val : res) cout << val << " ";
    cout << endl;

    return 0;
}
Java
import java.util.Deque; 
import java.util.ArrayList; 
import java.util.ArrayDeque; 


class GfG {
    static ArrayList<Integer> maxOfMin(int arr[]) {
        
        int n = arr.length;
        ArrayList<Integer> res = new ArrayList<>();
        
        // iterate over all window sizes
        for (int k = 1; k <= n; k++) {
            Deque<Integer> dq = new ArrayDeque<>();
            int maxMin = Integer.MIN_VALUE;

            // process first k elements
            for (int i = 0; i < k; i++) {
                while (!dq.isEmpty() && arr[i] <= arr[dq.peekLast()])
                    dq.pollLast();
                dq.offerLast(i);
            }

            // slide the window
            for (int i = k; i < n; i++) {
                maxMin = Math.max(maxMin, arr[dq.peekFirst()]);

                while (!dq.isEmpty() && dq.peekFirst() <= i - k)
                    dq.pollFirst();
                while (!dq.isEmpty() && arr[i] <= arr[dq.peekLast()])
                    dq.pollLast();

                dq.offerLast(i);
            }

            maxMin = Math.max(maxMin, arr[dq.peekFirst()]);
            res.add(maxMin);
        }

        return res;
    }

    public static void main(String[] args) {
        int arr[] = {10, 20, 30, 50, 10, 70, 30};
        ArrayList<Integer> res = maxOfMin(arr);
        for (int val : res) System.out.print(val + " ");
        System.out.println();
    }
}
Python
from collections import deque
import sys

def maxOfMin(arr):
    n = len(arr);
    res = []

    # iterate over all window sizes
    for k in range(1, n + 1):
        dq = deque()
        maxMin = -sys.maxsize

        # process first k elements
        for i in range(k):
            while dq and arr[i] <= arr[dq[-1]]:
                dq.pop()
            dq.append(i)

        # slide the window
        for i in range(k, n):
            maxMin = max(maxMin, arr[dq[0]])

            while dq and dq[0] <= i - k:
                dq.popleft()
            while dq and arr[i] <= arr[dq[-1]]:
                dq.pop()

            dq.append(i)

        maxMin = max(maxMin, arr[dq[0]])
        res.append(maxMin)

    return res

if __name__ == "__main__":
    arr = [10, 20, 30, 50, 10, 70, 30]
    res = maxOfMin(arr)
    for val in res:
        print(val, end=" ")
    print()
C#
using System;
using System.Collections.Generic;

class GfG {
    static List<int> maxOfMin(int[] arr) {
        int n = arr.Length;
        List<int> res = new List<int>();

        // iterate over all window sizes
        for (int k = 1; k <= n; k++) {
            LinkedList<int> dq = new LinkedList<int>();
            int maxMin = int.MinValue;

            // process first k elements
            for (int i = 0; i < k; i++) {
                while (dq.Count > 0 && arr[i] <= arr[dq.Last.Value])
                    dq.RemoveLast();
                dq.AddLast(i);
            }

            // slide the window
            for (int i = k; i < n; i++) {
                maxMin = Math.Max(maxMin, arr[dq.First.Value]);

                while (dq.Count > 0 && dq.First.Value <= i - k)
                    dq.RemoveFirst();
                while (dq.Count > 0 && arr[i] <= arr[dq.Last.Value])
                    dq.RemoveLast();

                dq.AddLast(i);
            }

            maxMin = Math.Max(maxMin, arr[dq.First.Value]);
            res.Add(maxMin);
        }

        return res;
    }

    public static void Main() {
        int[] arr = {10, 20, 30, 50, 10, 70, 30};
        List<int> res = maxOfMin(arr);
        foreach (int val in res) Console.Write(val + " ");
        Console.WriteLine();
    }
}
JavaScript
function maxOfMin(arr) {
    
    let n = arr.length;
    let res = [];

    // iterate over all window sizes
    for (let k = 1; k <= n; k++) {
        let dq = [];
        let maxMin = Number.MIN_SAFE_INTEGER;

        // process first k elements
        for (let i = 0; i < k; i++) {
            while (dq.length > 0 && arr[i] <= arr[dq[dq.length - 1]])
                dq.pop();
            dq.push(i);
        }

        // slide the window
        for (let i = k; i < n; i++) {
            maxMin = Math.max(maxMin, arr[dq[0]]);

            while (dq.length > 0 && dq[0] <= i - k)
                dq.shift();
            while (dq.length > 0 && arr[i] <= arr[dq[dq.length - 1]])
                dq.pop();

            dq.push(i);
        }

        maxMin = Math.max(maxMin, arr[dq[0]]);
        res.push(maxMin);
    }

    return res;
}

// Driver Code
let arr = [10, 20, 30, 50, 10, 70, 30];
let res = maxOfMin(arr);
console.log(res.join(" "));

Output
70 30 20 10 10 10 10 

[Expected Approach] Using Stack - O(n) Time and O(n) Space

Observation:

  • Each element has a natural “range of control” where it is the minimum. This range is bounded on the left by the nearest smaller element before it, and bounded on the right by the nearest smaller element after it.
  • Within this range, arr[i] will be the minimum for all window sizes that fit inside.
  • So the problem reduces to: For each element arr[i], find the length of the largest window where it is the minimum. Then assign arr[i] as a candidate answer for that window size.
  • Propagate results backwards because smaller windows must have at least as large answers as bigger windows.

Idea: Now we have to find the next smaller and previous smaller elements for each item in the array. Using these, we calculate the length of the window where the current element is the smallest. Then, we update the result for that window size with the maximum value seen so far.

C++
#include <iostream>
#include <vector>
#include <stack>
using namespace std;

vector<int> maxOfMin(vector<int>& arr) {
    int n = arr.size();
    vector<int> res(n), len(n + 1, 0);
    stack<int> st;

    // find window sizes for each element
    for (int i = 0; i < n; i++) {
        while (!st.empty() && arr[st.top()] >= arr[i]) {
            int top = st.top();
            st.pop();
            int left = st.empty() ? -1 : st.top();
            int right = i;
            int windowSize = right - left - 1;
            len[windowSize] = max(len[windowSize], arr[top]);
        }
        st.push(i);
    }

    // process remaining elements in stack
    while (!st.empty()) {
        int top = st.top();
        st.pop();
        int left = st.empty() ? -1 : st.top();
        int right = n;
        int windowSize = right - left - 1;
        len[windowSize] = max(len[windowSize], arr[top]);
    }

    for (int i = 1; i <= n; i++) {
        res[i - 1] = len[i];
    }

    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 = maxOfMin(arr);
    for (int val : res) cout << val << " ";
    cout << endl;
    return 0;
}
Java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.ArrayDeque;
import java.util.Arrays;

class GfG {

    static ArrayList<Integer> maxOfMin(int[] arr) {
        int n = arr.length;
        ArrayList<Integer> res = 
            new ArrayList<>(Collections.nCopies(n, 0));
        ArrayList<Integer> len = 
            new ArrayList<>(Collections.nCopies(n + 1, 0));
        Deque<Integer> stack = new ArrayDeque<>();

        // Compute previous and next smaller elements using monotonic stack
        for (int i = 0; i < n; i++) {
            while (!stack.isEmpty() && arr[stack.peek()] >= arr[i]) {
                int top = stack.pop();
                int left = stack.isEmpty() ? -1 : stack.peek();
                int right = i;
                int windowSize = right - left - 1;
                len.set(windowSize, 
                    Math.max(len.get(windowSize), arr[top]));
            }
            stack.push(i);
        }

        // Process remaining elements
        while (!stack.isEmpty()) {
            int top = stack.pop();
            int left = stack.isEmpty() ? -1 : stack.peek();
            int right = n;
            int windowSize = right - left - 1;
            len.set(windowSize, 
                Math.max(len.get(windowSize), arr[top]));
        }

        // Fill result using len[]
        for (int i = 1; i <= n; i++) {
            res.set(i - 1, len.get(i));
        }

        // Ensure result is non-increasing
        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 = maxOfMin(arr);
        for (int val : res) {
            System.out.print(val + " ");
        }
        System.out.println();
    }
}
Python
def maxOfMin(arr):
    n = len(arr)
    res = [0] * n
    windowMax = [0] * (n + 1)
    st = []

    # Find previous and next smaller elements
    for i in range(n):
        while st and arr[st[-1]] >= arr[i]:
            top = st.pop()
            left = st[-1] if st else -1
            right = i
            wsize = right - left - 1
            windowMax[wsize] = max(windowMax[wsize], arr[top])
        st.append(i)

    # Process remaining elements in the stack
    while st:
        top = st.pop()
        left = st[-1] if st else -1
        right = n
        wsize = right - left - 1
        windowMax[wsize] = max(windowMax[wsize], arr[top])

    # Fill the result list
    for i in range(n):
        res[i] = windowMax[i + 1]

    # Ensure results are non-increasing
    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]
    result = maxOfMin(arr)
    print(" ".join(map(str, result)))
C#
using System;
using System.Collections.Generic;

class GfG {
    static List<int> maxOfMin(int[] arr) {
        int n = arr.Length;
        List<int> res = new List<int>(new int[n]);
        int[] windowMax = new int[n + 1];
        Stack<int> st = new Stack<int>();

        // find window sizes for each element
        for (int i = 0; i < n; i++) {
            while (st.Count > 0 && arr[st.Peek()] >= arr[i]) {
                int top = st.Pop();
                int left = st.Count == 0 ? -1 : st.Peek();
                int right = i;
                int windowSize = right - left - 1;
                windowMax[windowSize] = Math.Max(windowMax[windowSize], arr[top]);
            }
            st.Push(i);
        }

        // process remaining elements in stack
        while (st.Count > 0) {
            int top = st.Pop();
            int left = st.Count == 0 ? -1 : st.Peek();
            int right = n;
            int windowSize = right - left - 1;
            windowMax[windowSize] = Math.Max(windowMax[windowSize], arr[top]);
        }

        for (int i = 0; i < n; i++) {
            res[i] = windowMax[i + 1];
        }

        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 = maxOfMin(arr);
        foreach (int val in res)
            Console.Write(val + " ");
        Console.WriteLine();
    }
}
JavaScript
function maxOfMin(arr) {
    const n = arr.length;
    const res = new Array(n).fill(0);
    const windowMax = new Array(n + 1).fill(0);
    const st = [];

    // find window sizes for each element
    for (let i = 0; i < n; i++) {
        while (st.length && arr[st[st.length - 1]] >= arr[i]) {
            const top = st.pop();
            const left = st.length ? st[st.length - 1] : -1;
            const right = i;
            const windowSize = right - left - 1;
            windowMax[windowSize] = Math.max(windowMax[windowSize], arr[top]);
        }
        st.push(i);
    }

    // process remaining elements in stack
    while (st.length) {
        const top = st.pop();
        const left = st.length ? st[st.length - 1] : -1;
        const right = n;
        const windowSize = right - left - 1;
        windowMax[windowSize] = Math.max(windowMax[windowSize], arr[top]);
    }

    // build result array
    for (let i = 0; i < n; i++) {
        res[i] = windowMax[i + 1];
    }

    // ensure non-increasing order
    for (let i = n - 2; i >= 0; i--) {
        res[i] = Math.max(res[i], res[i + 1]);
    }

    return res;
}

// Driver Code
const arr = [10, 20, 30, 50, 10, 70, 30];
const res = maxOfMin(arr);
console.log(res.join(' '));

Output
70 30 20 10 10 10 10 

Article Tags :

Explore