题目
给定一个整数序列: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].
题解
首先懒得多想,直接暴力搜索完事了。
aj 是三个数中的最大值,所以先找到数组中的最大值 j_val,然后搜索左边的最小值为 i_val。
接下来在数组右边寻找满足条件i_val < nums[k] < j_val的数即可。
如果没找到满足条件的数,就将数组分成两部分,再分别在两个子数组中搜索。
class Solution:
def find132pattern(self, nums: List[int]) -> bool:
if len(nums) < 3:
return False
j_val = max(nums)
j = nums.index(j_val)
if 0 < j < len(nums)-1:
i_val = min(nums[:j])
for k in range(j+1, len(nums)):
if i_val < nums[k] < j_val:
return True
return self.find132pattern(nums[:j]) or self.find132pattern(nums[j+1:])
思想很简单粗暴,所以速度理所当然的也很慢,于是开始思考第二种方法。
方法2
先维护一个最小值数组,用 Mi[i] 记录数组前 i 个数中的最小值。
然后用 j 从后往前遍历,并维护一个从大到小的单调栈,同时栈中所有元素必须比Mi[j] 大。
对于当前元素 nums[j],如果它能比栈顶元素 L[-1] 大,那么显然就是符合条件的了。
class Solution:
def find132pattern(self, nums: List[int]) -> bool:
n = len(nums)
Mi = [nums[0]]*n
for i in range(1, n):
Mi[i] = min(Mi[i-1], nums[i])
L = []
for j in range(n-1, 0, -1):
while L and Mi[j-1] >= L[-1]:
L.pop()
if L == [] or Mi[j-1] < nums[j] < L[-1]:
L.append(nums[j])
elif nums[j] > L[-1] > Mi[j-1]:
return True
return False
