揭秘“132 模式”子序列,解锁单调栈的奥秘
2023-03-29 20:29:29
132 模式:单调栈算法详解
在数字的世界里,存在着一种有趣的模式,被称为 132 模式。这个模式了一种整数数组中的特殊排列,其中存在三个整数 i、j 和 k,满足 i < j < k 且满足 nums[i] < nums[k] < nums[j]。换句话说,最小的数字位于最左边,最大的数字位于最右边,而中间的数字既大于左边,又小于右边。
132 模式的发现
要发现一个数组中是否存在 132 模式,我们需要遍历数组中的每个元素,并检查每个元素是否符合 132 模式的条件。如果满足,我们就能找到一个 132 模式。
然而,这种遍历方式的效率较低,因为它需要多次遍历数组。为了提高效率,我们可以引入单调栈这一强大的数据结构。
单调栈:一个神奇的数据结构
单调栈是一种特殊类型的栈,它遵循以下规则:
- 栈中元素按照某种顺序排列,可能是升序或降序。
- 栈中的元素不能被删除,只能被压入或弹出。
- 栈顶元素始终是栈中最大的元素(如果是升序栈)或最小的元素(如果是降序栈)。
想象一个装满数字的盒子,这个盒子就是单调栈。当我们压入一个数字时,如果它比栈顶元素小(如果是升序栈)或大(如果是降序栈),我们就将它压入栈中。如果它比栈顶元素大(如果是升序栈)或小(如果是降序栈),我们就弹出栈顶元素,直到栈顶元素满足条件为止。
使用单调栈寻找 132 模式
现在,我们已经了解了单调栈的威力,可以利用它来高效地寻找 132 模式。
- 初始化单调栈: 创建一个空栈,作为升序单调栈。
- 遍历数组: 从左到右遍历数组中的每个元素。
- 检查元素: 对于每个元素,如果它满足 132 模式的条件(即 nums[i] < nums[k] < nums[j]),我们就找到了一个 132 模式。
- 压入或弹出: 如果元素不满足 132 模式的条件,我们将它压入栈中。如果栈顶元素满足 132 模式的条件,我们就弹出栈顶元素。
- 重复步骤 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),因为我们需要使用单调栈来存储数组中的元素。
常见问题解答
-
什么是 132 模式?
答:132 模式是一种出现在整数数组中的特殊排列,其中存在三个整数 i、j 和 k,满足 i < j < k 且满足 nums[i] < nums[k] < nums[j]。 -
单调栈是什么?
答:单调栈是一种特殊类型的栈,它遵循以下规则:栈中元素按照某种顺序排列,可能是升序或降序;栈中的元素不能被删除,只能被压入或弹出;栈顶元素始终是栈中最大的元素(如果是升序栈)或最小的元素(如果是降序栈)。 -
如何使用单调栈寻找 132 模式?
答:初始化一个空栈,作为升序单调栈;遍历数组中的每个元素,如果它满足 132 模式的条件,我们就找到了一个 132 模式;如果它不满足条件,我们将它压入栈中;如果栈顶元素满足条件,我们就弹出栈顶元素;继续遍历数组,直到所有元素都被处理完。 -
132 模式算法的时间复杂度是多少?
答:时间复杂度为 O(n),其中 n 是数组的长度。 -
132 模式算法的空间复杂度是多少?
答:空间复杂度也是 O(n),因为我们需要使用单调栈来存储数组中的元素。