一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情。
题目描述
给你一个整数数组 nums
,数组中共有 n
个整数。132 模式的子序列 由三个整数 nums[i]
、nums[j]
和 nums[k]
组成,并同时满足:i < j < k
和 nums[i] < nums[k] < nums[j]
。
如果 nums
中存在 132 模式的子序列 ,返回 true
;否则,返回 false
。
示例
输入: nums = [1,2,3,4]
输出: false
解释: 序列中不存在 132 模式的子序列。
输入: nums = [3,1,4,2]
输出: true
解释: 序列中有 1 个 132 模式的子序列: [1, 4, 2] 。
输入:nums = [-1,3,2,0]
输出:true
解释:序列中有 3 个 132 模式的的子序列:[-1, 3, 2]、[-1, 3, 0] 和 [-1, 2, 0] 。
提示
n == nums.length
1 <= n <= 2 * 10
-10
<= nums[i] <= 10
单调栈
我们可以利用栈后进先出的特性来保存遍历过的元素,当遇到比栈顶元素还大的数值时,我们需要将其从栈顶弹出,复制给 132
中的2
,再将新的数值入栈,到了这里,我们132
中的32
已经有了,如果在接下来的遍历在,发现有比2
更小的数值,即表示该条件满足,直接返回结果。否则重复前面的比较步骤,直至遍历完整个数组。
class Solution {
public boolean find132pattern(int[] nums) {
// 定义栈,用来保存 132 中的 3
Stack<Integer> stack = new Stack<>();
// 右边的变量,相当于是 2
int right = Integer.MIN_VALUE;
// 从右往左遍历
for(int left = nums.length - 1; left >= 0; --left){
// 当前位置元素小于 2 时,代表找到 132 模式的子序列
if(nums[left] < right){
return true;
}
// 当遇到比 3 栈顶的数值更大的元素时,将 3 栈顶元素弹出,传递给 2
while(!stack.isEmpty() && stack.peek() < nums[left]){
right = stack.pop();
}
stack.add(nums[left]);
}
return false;
}
}
数组模拟栈
解题思路跟单调栈是一样的,不同的地方在于这里将栈缓存了数组,通过指针的移动来保存跟获取元素。
class Solution {
public boolean find132pattern(int[] nums) {
int n = nums.length;
// 模拟栈的数组
int[] stack = new int[n + 1];
// 指针与 2号位元素
int idx = 0, right = Integer.MIN_VALUE;
// 从右往左遍历
for(int left = n - 1; left >= 0; --left){
// 当前位置元素小于 2 时,代表找到 132 模式的子序列
if(nums[left] < right){
return true;
}
// 当遇到比 3 栈顶的数值更大的元素时,将 3 栈顶元素弹出,传递给 2
while(idx > 0 && nums[left] > stack[idx]){
right = stack[idx--];
}
stack[++idx] = nums[left];
}
return false;
}
}