【题目】
给定一个整数序列:a1, a2, ..., an,一个132模式的子序列 ai, aj, ak 被定义为:当 i < j < k 时,ai < ak < aj。设计一个算法,当给定有 n 个数字的序列时,验证这个序列中是否含有132模式的子序列。
注意:n 的值小于15000。
示例1:
输入: [1, 2, 3, 4]
输出: False
解释: 序列中不存在132模式的子序列。
示例 2:
输入: [3, 1, 4, 2]
输出: True
解释: 序列中有 1 个132模式的子序列: [1, 4, 2].
示例 3:
输入: [-1, 3, 2, 0]
输出: True
解释: 序列中有 3 个132模式的的子序列: [-1, 3, 2], [-1, 3, 0] 和 [-1, 2, 0].
【分析】
从题目中可以看出,我们需要找到这样的子序列,min < middle < max 时,Amin < Amax < Amiddle。
开始我的思路是对题目中给出的序列做三次遍历,找到这样的子序列则返回True,否则返回False。但是,在编写代码的过程中发现因为这个子序列中的元素可以不是连续的,所以可能会漏掉一些情况,而且这种方法的时间复杂度太高,不可取。
后来,去了解了大众的解法——利用栈,但是不是单纯的使用栈,而是很巧妙的使用栈来存储最大值。
【栈解法】
- 使用min来存放当前最小的值,
- 将当前值和stack栈的栈顶元素比较,如果当前元素大于栈顶元素,则将栈顶元素出栈,并将栈顶元素赋值给min来存放。
- 判断如果当前值小于min值,则说明当前值是最小值,而栈中元素为最大值,min值为中间值,而当前值的索引<最大值的索引<min值的索引。
【例子】
1. 从后往前遍历,当栈为空时,将当前元素直接入栈
2. 继续遍历,并且进行判断,如果栈不为空,则比较栈顶元素和当前元素,如果当前元素大于栈顶元素,将栈顶元素出栈赋值给min来存放。
3. 继续遍历,并进行判断,如果当前元素小于min的值,则说明当前值是最小值,而栈中元素为最大值,min值为中间值,而当前值的索引<最大值的索引<min值的索引,返回True。
【python代码】
class Solution:
def find132pattern(self, nums: list) -> bool:
stack = []
min = float('-inf')
for i in range(len(nums)-1,-1,-1):
if nums[i] < min:
return True
while len(stack) != 0 and nums[i] > stack[-1]:
min = stack.pop()
stack.append(nums[i])
return False
s = Solution()
nums = [3,1,4,2]
print(s.find132pattern(nums))