所有子数组最小值中的最大值
难度:
标签:
题目描述
代码结果
运行时间: 204 ms, 内存: 33.2 MB
/*
* LeetCode Problem 1950: Maximum of Minimum Values in All Subarrays using Java Streams
*
* Problem Statement:
* Given an array of integers, find the maximum of the minimum values in all subarrays of the array.
*
* Approach:
* 1. Use a monotonic stack to find the previous and next less elements for each element in the array.
* 2. Calculate the contribution of each element as the minimum in its subarrays.
* 3. Aggregate the results to find the maximum of these minimum values.
*/
import java.util.Arrays;
import java.util.Stack;
public class Solution {
public int maxOfMinValues(int[] arr) {
int n = arr.length;
int[] previousLess = new int[n];
int[] nextLess = new int[n];
Stack<Integer> stack = new Stack<>();
// Find previous less for each element
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && arr[stack.peek()] >= arr[i]) {
stack.pop();
}
previousLess[i] = (stack.isEmpty()) ? -1 : stack.peek();
stack.push(i);
}
stack.clear();
// Find next less for each element
for (int i = n - 1; i >= 0; i--) {
while (!stack.isEmpty() && arr[stack.peek()] >= arr[i]) {
stack.pop();
}
nextLess[i] = (stack.isEmpty()) ? n : stack.peek();
stack.push(i);
}
// Calculate maximum of minimum values in all subarrays
int[] result = new int[n + 1];
Arrays.fill(result, Integer.MIN_VALUE);
for (int i = 0; i < n; i++) {
int length = nextLess[i] - previousLess[i] - 1;
result[length] = Math.max(result[length], arr[i]);
}
// Fill in the rest of the results array
for (int i = n - 1; i >= 1; i--) {
result[i] = Math.max(result[i], result[i + 1]);
}
return result[1]; // result[1] holds the final answer
}
public static void main(String[] args) {
Solution sol = new Solution();
int[] arr = {1, 2, 3, 4, 5};
System.out.println(sol.maxOfMinValues(arr)); // Expected output: 1
}
}
解释
方法:
此题解采用单调栈和动态规划的思想来寻找所有子数组的最小值中的最大值。首先,使用单调栈来确定每个元素作为最小值可以扩展到的最左和最右边界。数组left和right分别存储每个元素作为最小值时,左边和右边的边界索引。接着,利用这些边界信息,计算每个可能的子数组长度(从1到n)中的最小值的最大值,并存储在数组ans中。最后,从后向前遍历数组ans,确保每一个长度的最小值的最大值是正确的(即长度为k的所有子数组的最小值的最大值,不会小于长度为k+1的对应值)。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在单调栈的使用中,为什么选择使用单调递增栈而不是单调递减栈来确定元素的左右边界?
▷🦆
你是如何确保每个元素作为最小值时,其左右边界值left和right的正确性的?有没有可能出现漏判或者重复判定的情况?
▷🦆
为什么在更新ans数组时,使用的索引是`r-l-2`?这个计算方式背后的逻辑是什么?
▷🦆
在反向遍历ans数组时,你提到要`确保每一个长度的最小值的最大值是正确的`,这个操作的目的是什么?为什么单纯的正向填充ans数组不能保证值的正确性?
▷