题目描述:
给定一个整数序列: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、问题转化为在位置 j 处,能不能在0~j-1的位置找到一个数m1,m1<nums[j];在j+1~n的位置找到一个数m2,m2<nums[j],且m1<m2
2、定义一个容器m,保存 0~j-1的最小值,这样就找到m1=m[j]。选择最小值,这样使符合m2的值范围更大
3、定义一个栈,倒序遍历,在m[j]<nums[j]时,判断栈顶元素是否大于m1,小于则弹出栈顶元素,直到栈顶元素大于m1,再判断栈顶元素是否小于nums[j],成立则符合132模式,否则将nums[j]压入栈中
4、容器m的元素是递减的(有相同元素),那么在倒序遍历数组的情况下,栈顶元素小于当前的m1,肯定也小于之后的m1。
5、每次弹出栈顶元素结束后,栈内元素的值都大于当前的m1
代码:
class Solution {
public:
bool find132pattern(vector<int>& nums) {
if(nums.size()<3)
return false;
stack<int> st;
vector<int>m;
m.push_back(nums[0]);
for(int i=1;i<nums.size();i++)
m.push_back(min(m[i-1],nums[i]));
for(int i=nums.size()-1;i>=0;i--)
{
if(m[i]<nums[i])
{
while(!st.empty()&&st.top()<=m[i])
st.pop();
if(!st.empty()&&st.top()<nums[i])
return true;
st.push(nums[i]);
}
}
return false;
}
};