给定一个整数序列: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].
题解:
如果直接暴力,那么就会达到O(n3)的时间复杂度,实际上这个题连时间复杂度O(n2)都过不了。
本题的解法是维护一个从左向右的最小数组,和一个从右向左的递减栈。
如下所示:
到这里,看到栈顶元素大于min,并且小于当前元素0.说明已经找到了满足132的模式串。可以返回了。
这里最小栈的栈顶一定只能保存比当前元素小并且比当前min大的数。所以每次要根据min对战进行弹出。保证栈顶是大于min的。而且如果此时栈顶元素小于当前元素说明找到了,不然将当前元素放入栈顶,继续下一个找。这样维护的栈是一个递减栈。
时间复杂度O(n)
空间复杂度O(n)
java代码:
public boolean find132pattern(int[] nums) {
if(nums.length<3)return false;
int[] left = new int[nums.length];
Stack<Integer> right =new Stack<>();
left[0] = nums[0];
for(int i = 0;i<nums.length;i++){
left[i] = Math.min(nums[i],left[i-1]);
}
for(int i = nums.length-1;i>=0;i--){
if(right.isEmpty()){
right.push(nums[i]);
continue;
}
while(right.peek()<=left[i]){
right.pop();
}
if(right.isEmpty()){
right.push(nums[i]);
continue;
}
if(right.peek()<nums[i])
return true;
else
right.push(nums[i]);
}
return false;
}