给定一个整数序列: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].
思路:首先我们需要预处理一下前缀最小值,这样我们能保证a[i]是最优(小)的a[i],然后我们维护一个栈,这个栈里的元素是从后往前遍历并且大于等于mins[i]的元素,且栈里的元素是降序的(栈顶是最小值),之后我们从后往前遍历数组,若当前元素小于等于mins[i],则跳过。若当前元素大于mins[i]并且大于栈顶元素则一定是true,否则将该元素加入栈。
class Solution {
public boolean find132pattern(int[] nums) {
if(nums.length<=2) return false;
int[] mins=new int[nums.length];
Stack<Integer> st=new Stack<>();
mins[0]=nums[0];
for(int i=1;i<nums.length;i++)
mins[i]=Math.min(nums[i], mins[i-1]);
for(int i=nums.length-1;i>=0;i--) {
if(nums[i]<=mins[i])
continue;
while(!st.isEmpty() && st.peek()<=mins[i])
st.pop();
if(!st.isEmpty() && st.peek()<nums[i])
return true;
st.push(nums[i]);
}
return false;
}
}