leetcode
leetcode 851 ~ 900
最大宽度坡

最大宽度坡

难度:

标签:

题目描述

代码结果

运行时间: 45 ms, 内存: 21.6 MB


/*
 * 思路:
 * 1. 使用Stream API处理数组A,利用stack辅助进行递减序列的维护。
 * 2. 使用stream进行遍历时,需要先从右到左找到最大的坡宽度。
 * 3. 最终结果使用Optional来处理,确保无坡时返回0。
 */

import java.util.*;
import java.util.stream.*;

public class MaxWidthRampStream {
    public int maxWidthRamp(int[] A) {
        Deque<Integer> stack = new LinkedList<>();
        IntStream.range(0, A.length).forEach(i -> {
            if (stack.isEmpty() || A[stack.peek()] > A[i]) {
                stack.push(i);
            }
        });

        OptionalInt maxWidth = IntStream.range(0, A.length)
            .mapToObj(j -> new int[] {j})
            .sorted((a, b) -> b[0] - a[0])
            .flatMapToInt(jArr -> {
                int j = jArr[0];
                int[] max = {0};
                while (!stack.isEmpty() && A[stack.peek()] <= A[j]) {
                    max[0] = Math.max(max[0], j - stack.pop());
                }
                return IntStream.of(max[0]);
            })
            .max();

        return maxWidth.orElse(0);
    }
}

解释

方法:

该题解采用单调栈的方法来求解最大宽度坡问题。首先,构建一个单调递减栈,栈中存储数组元素的索引,确保栈中的元素对应的数组值是递减的。这样做的目的是为了后面从数组尾部开始向前遍历时,能快速找到满足条件的坡底(即数组中较小的值)。在遍历过程中,对于每个元素,试图找到一个坡底,使得坡底的值不大于当前元素的值。如果找到了这样的坡底,那么计算当前的宽度(当前索引减去坡底索引),并更新最大宽度。重复这个过程直到遍历完数组或栈为空。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在构建单调递减栈时,只有当当前元素小于栈顶元素时才将其索引入栈?
在构建单调递减栈的过程中,目标是保持栈内元素对应的数组值是递减的。这样做的原因是,栈中每个元素的索引代表了一个潜在的坡底。如果遇到一个较小的元素,将其索引入栈,可以确保在后面寻找坡顶时,能找到尽可能早的坡底索引,从而最大化坡的宽度。如果当前元素大于或等于栈顶元素,则意味着它不能作为一个有效的更早的坡底,因为它在数组中的位置更靠后,且值不小于前面的元素。
🦆
在从后向前遍历数组时,为什么要检查当前元素是否大于等于栈顶元素对应的值?
从后向前遍历数组时,目标是找到一个有效的坡顶,即数组中较大的值,且能与栈中记录的坡底索引形成最大宽度的坡。检查当前元素是否大于等于栈顶元素对应的值是为了确保找到一个有效的坡顶(当前元素)和坡底(栈顶元素对应的值)。只有当当前元素大于等于栈顶元素时,当前的索引与栈顶索引之间才符合坡的定义(坡顶不小于坡底),因此可以计算宽度并尝试更新最大宽度。
🦆
在最后向后遍历数组计算最大宽度时,弹出栈顶元素的条件是什么?为什么选择这样的条件?
弹出栈顶元素的条件是当前元素(从数组末端向前遍历时的元素)必须大于等于栈顶元素对应的值。这一条件的选择是因为,一旦当前元素大于等于栈顶元素,说明找到了一个有效的坡顶,与栈顶元素对应的坡底可以形成一个坡。此时,可以计算当前坡的宽度,并更新可能的最大宽度。此外,弹出栈顶元素后,栈中下一个元素(如果存在)将成为新的坡底候选,可以继续检查是否能形成更宽的坡。
🦆
如果数组中包含重复元素,单调栈方法是否仍然有效?会有哪些特别的情况需要考虑?
如果数组中包含重复元素,单调栈方法仍然有效。在构建单调递减栈时,如果当前元素等于栈顶元素,通常不会将其索引入栈,因为已经有一个相同值的索引,且位置更靠前。这保证了在后续寻找坡顶时,可以保持最大的宽度。但需要注意,当从数组末端向前遍历时,遇到与栈顶元素相等的情况,同样可以形成坡,并尝试更新最大宽度,因为这样可以利用到重复值之间的宽度。

相关问题