Max of Mins for All Window Sizes

Last Updated : 29 Jul, 2026

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.

Examples:

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.

Input: arr[] = [10, 20, 30]
Output: [30, 20, 10]
Explanation:
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.

Try It Yourself
redirect icon

[Naive Approach] By Checking All Subarrays - O(n^3) Time and O(1) Space

The idea is to consider every possible window size from 1 to n. For each window size, traverse all possible subarrays (windows) of that size, find the minimum element in each window, and keep track of the maximum among all these minimum values. Store this value as the answer for that window size.

Working of Approach:

  • Traverse every possible window size from 1 to n.
  • For each window size, slide the window across the array and consider every possible subarray.
  • Find the minimum element in each current window by scanning all its elements.
  • Keep track of the maximum among these minimum values for the current window size.
  • Store this maximum value in the result array and repeat the process for all window sizes.
C++
#include <iostream>
#include <vector>
#include <climits>
using namespace std;

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

public class GFG {
    public static ArrayList<Integer> maxOfMins(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 = maxOfMins(arr);
        
        for (int val : res) {
            System.out.print(val + " ");
        }
        System.out.println();
    }
}
Python
def maxOfMins(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 = maxOfMins(arr)
    
    print(" ".join(map(str, res)))
C#
using System;
using System.Collections.Generic;

class GFG {
    public static List<int> maxOfMins(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 = maxOfMins(arr);

        Console.Write(string.Join(" ", res));
        Console.WriteLine();
    }
}
JavaScript
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++) {
    
        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 Code
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 

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

The idea is to use a deque to efficiently keep track of the minimum element in each window. For every window size, slide the window across the array, get the minimum from the front of the deque, and store the maximum among all these minimum values as the answer.

Working of Approach:

  • Traverse every window size from 1 to n.
  • For each window size, maintain a monotonic increasing deque of indices so that the front always represents the minimum element of the current window.
  • As the window slides, remove indices that are out of the current window and discard larger elements from the back before inserting the new element.
  • The element at the front of the deque gives the minimum of the current window in O(1) time.
  • Keep updating the maximum among all window minimums and store it as the answer for the current window size.
C++
#include <iostream>
#include <vector>
#include <deque>
#include <climits>
using namespace std;

vector<int> maxOfMins(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 = maxOfMins(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> maxOfMins(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 = maxOfMins(arr);
        for (int val : res) System.out.print(val + " ");
        System.out.println();
    }
}
Python
from collections import deque
import sys

def maxOfMins(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 = maxOfMins(arr)
    for val in res:
        print(val, end=" ")
    print()
C#
using System;
using System.Collections.Generic;

class GFG {
    static List<int> maxOfMins(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 = maxOfMins(arr);
        foreach (int val in res) Console.Write(val + " ");
        Console.WriteLine();
    }
}
JavaScript
function maxOfMins(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 = 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 use a monotonic increasing stack to find the previous smaller and next smaller element for every array element. These boundaries give the largest window where the current element is the minimum. Update the answer for that window size, then propagate the results backward to fill the remaining answers.

Working of Approach:

  • Traverse the array using a monotonic increasing stack to find the maximum window where each element is the minimum.
  • For each element, calculate its window size using the previous and next smaller elements.
  • Update the answer for that window size with the maximum minimum value.
  • Process the remaining elements left in the stack after traversal.
  • Traverse the result array from right to left to fill missing values and obtain the final answer.

Let us understand with an example:
Input: arr[] = [10, 20, 30, 50, 10, 70, 30]

  • Traverse the array using a monotonic increasing stack. Whenever a smaller element is found, pop elements from the stack and compute the largest window in which each popped element is the minimum.
  • For example, when the second 10 is encountered, elements 50, 30, and 20 are popped, giving window sizes 1, 2, and 3, and the answers for these window sizes are updated.
  • After the traversal, process the remaining elements left in the stack by assuming their next smaller element is beyond the end of the array, and update their corresponding window sizes.
  • Copy the computed values for each window size into the result array.
  • Finally, traverse the result array from right to left to propagate larger values, giving the final answer: [70, 30, 20, 10, 10, 10, 10].
C++
#include <iostream>
#include <vector>
#include <stack>
using namespace std;

vector<int> maxOfMins(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 = maxOfMins(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> maxOfMins(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 = maxOfMins(arr);
        for (int val : res) {
            System.out.print(val + " ");
        }
        System.out.println();
    }
}
Python
def maxOfMins(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 = maxOfMins(arr)
    print(" ".join(map(str, result)))
C#
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]);
        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 = maxOfMins(arr);
        foreach (int val in res)
            Console.Write(val + " ");
        Console.WriteLine();
    }
}
JavaScript
function maxOfMins(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 = maxOfMins(arr);
console.log(res.join(' '));

Output
70 30 20 10 10 10 10 
Comment