返回

揭秘“132 模式”子序列,解锁单调栈的奥秘

后端

132 模式:单调栈算法详解

在数字的世界里,存在着一种有趣的模式,被称为 132 模式。这个模式了一种整数数组中的特殊排列,其中存在三个整数 i、j 和 k,满足 i < j < k 且满足 nums[i] < nums[k] < nums[j]。换句话说,最小的数字位于最左边,最大的数字位于最右边,而中间的数字既大于左边,又小于右边。

132 模式的发现

要发现一个数组中是否存在 132 模式,我们需要遍历数组中的每个元素,并检查每个元素是否符合 132 模式的条件。如果满足,我们就能找到一个 132 模式。

然而,这种遍历方式的效率较低,因为它需要多次遍历数组。为了提高效率,我们可以引入单调栈这一强大的数据结构。

单调栈:一个神奇的数据结构

单调栈是一种特殊类型的栈,它遵循以下规则:

  • 栈中元素按照某种顺序排列,可能是升序或降序。
  • 栈中的元素不能被删除,只能被压入或弹出。
  • 栈顶元素始终是栈中最大的元素(如果是升序栈)或最小的元素(如果是降序栈)。

想象一个装满数字的盒子,这个盒子就是单调栈。当我们压入一个数字时,如果它比栈顶元素小(如果是升序栈)或大(如果是降序栈),我们就将它压入栈中。如果它比栈顶元素大(如果是升序栈)或小(如果是降序栈),我们就弹出栈顶元素,直到栈顶元素满足条件为止。

使用单调栈寻找 132 模式

现在,我们已经了解了单调栈的威力,可以利用它来高效地寻找 132 模式。

  1. 初始化单调栈: 创建一个空栈,作为升序单调栈。
  2. 遍历数组: 从左到右遍历数组中的每个元素。
  3. 检查元素: 对于每个元素,如果它满足 132 模式的条件(即 nums[i] < nums[k] < nums[j]),我们就找到了一个 132 模式。
  4. 压入或弹出: 如果元素不满足 132 模式的条件,我们将它压入栈中。如果栈顶元素满足 132 模式的条件,我们就弹出栈顶元素。
  5. 重复步骤 2-4: 继续遍历数组,直到所有元素都被处理完。

代码示例

def find132pattern(nums):
    stack = []  # 升序单调栈
    min_val = float('inf')  # 记录栈中的最小值

    for num in nums:
        if num < min_val:
            min_val = num
        elif num > min_val:
            while stack and stack[-1] <= num:
                stack.pop()
            if stack and stack[-1] < num:
                return True
        stack.append(num)

    return False

复杂度分析

使用单调栈寻找 132 模式的时间复杂度为 O(n),其中 n 是数组的长度。这是因为我们只需要遍历数组一次,并且在每个元素上进行常数时间操作。空间复杂度也是 O(n),因为我们需要使用单调栈来存储数组中的元素。

常见问题解答

  1. 什么是 132 模式?
    答:132 模式是一种出现在整数数组中的特殊排列,其中存在三个整数 i、j 和 k,满足 i < j < k 且满足 nums[i] < nums[k] < nums[j]。

  2. 单调栈是什么?
    答:单调栈是一种特殊类型的栈,它遵循以下规则:栈中元素按照某种顺序排列,可能是升序或降序;栈中的元素不能被删除,只能被压入或弹出;栈顶元素始终是栈中最大的元素(如果是升序栈)或最小的元素(如果是降序栈)。

  3. 如何使用单调栈寻找 132 模式?
    答:初始化一个空栈,作为升序单调栈;遍历数组中的每个元素,如果它满足 132 模式的条件,我们就找到了一个 132 模式;如果它不满足条件,我们将它压入栈中;如果栈顶元素满足条件,我们就弹出栈顶元素;继续遍历数组,直到所有元素都被处理完。

  4. 132 模式算法的时间复杂度是多少?
    答:时间复杂度为 O(n),其中 n 是数组的长度。

  5. 132 模式算法的空间复杂度是多少?
    答:空间复杂度也是 O(n),因为我们需要使用单调栈来存储数组中的元素。