📌  相关文章
📜  Array 中每个索引的最大范围子数组,使得 A[i] = min(A[L], A[L+1], ... A[R])(1)

📅  最后修改于: 2023-12-03 15:13:29.536000             🧑  作者: Mango

寻找Array中每个索引的最大范围子数组

在使用数组时,可能会遇到需要寻找某个索引的最大范围子数组的情况。这种情况下,我们需要找到数组中的一个子数组,使得这个子数组内的最小值即为该索引处的值。为了找到这个子数组,我们可以使用单调栈来优化时间复杂度。

算法步骤
  1. 我们从左往右依次遍历数组A,使用一个单调递增栈stack来记录每个元素的最左边的符合条件的位置。栈内的元素满足A[stack[-1]]到A[stack[0]]单调递增。
  2. 为了处理边界情况,在A后添加A[n] = float('inf'),其中n为A长度。这个inf可以理解为在右侧无穷远处有一个值为inf的元素,因此它一定不会在栈内被弹出,以避免边界情况的讨论。
  3. 我们从右往左依次遍历数组A,使用一个单调递增栈stack来记录每个元素的最右边的符合条件的位置。栈内的元素满足A[stack[-1]]到A[stack[0]]单调递增。
  4. 对于A的某个索引i,如果其左边最近的符合条件的位置为L,右边最近的符合条件的位置为R,则其最大范围子数组为A[L+1:R],因为L+1到R范围内的所有元素均大于或等于A[L],小于或等于A[i],而A[L]和A[R]均大于A[i],符合条件。
代码实现

下面是Python代码的实现,其中get_min_range函数接受一个数组A,返回一个列表ans,其中ans[i]表示以i为索引的最大范围子数组。

def get_min_range(A):
    n = len(A)
    left, right = [-1] * n, [n] * n

    stack = []
    for i in range(n):
        while stack and A[stack[-1]] >= A[i]:
            stack.pop()
        if stack:
            left[i] = stack[-1]
        stack.append(i)

    stack = []
    for i in range(n - 1, -1, -1):
        while stack and A[stack[-1]] >= A[i]:
            stack.pop()
        if stack:
            right[i] = stack[-1]
        stack.append(i)

    ans = []
    for i in range(n):
        ans.append(A[left[i]+1:right[i]])
    return ans
时间复杂度

在单调栈的过程中,每个元素只会进栈出栈一次,因此时间复杂度为O(n)。