题目:
给定一个整数序列: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].
题解:
这道题的关键是从后往前遍历,为什么呢?因为题目转换为我们要找到1,而1最可能就是在最前面出现的,作为坐标最小值也最小的数,因此更大的数3和2就从后面开始遍历。因为3和2的值越大越好。因此使用了递减栈,递减栈的作用是栈顶就是我们现在找到的最大的3,栈中的其他数虽然是大于3的,但是 不可能作为3,因为它们更可能是作为
[2 3 4]
这样的递减数组被加进来的,它们没有符合坐标比它们大,值又比它们小的2,因此就被压栈了。但是遍历时一旦发现有值比栈顶大,说明3值可以得到更新,更重要的是,它打破了递减数列,说明2是真实存在的,这也是2初始值为INT_MIN的原因。2当然也是越大越好,因此它就取值为被替换的3的旧值,刚好保证是次小于3的。
代码:
class Solution {
public:
bool find132pattern(vector<int>& nums) {
int second = INT_MIN;
stack<int>s;
for(int i = nums.size()-1;i>=0;i--)
{
if(nums[i] < second) return true;
while(!s.empty() && nums[i] > s.top())
{
second = s.top();
s.pop();
}
s.push(nums[i]);
}
return false;
}
};