题目:132模式
给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[i] < nums[k] < nums[j] 。
如果 nums 中存在 132 模式的子序列 ,返回 true ;否则,返回 false 。
示例 1:
输入: nums = [1,2,3,4]
输出: false
解释: 序列中不存在 132 模式的子序列。
示例 2:
输入: nums = [3,1,4,2]
输出: true
解释: 序列中有 1 个 132 模式的子序列: [1, 4, 2] 。
示例 3:
输入: nums = [-1,3,2,0]
输出: true
解释: 序列中有 3 个 132 模式的的子序列:[-1, 3, 2]、[-1, 3, 0] 和 [-1, 2, 0] 。
提示:
n == nums.length
解题思路
假设 i j k 三个数 i < k < j , i 对应最最小数 1 ,最大数 j 是 3, k大于 i,小于j。 以此枚举,只需要确定 i 我们再去比较 j 和 k 如果 j > k那么模式成立。 通过什么样的数据结构来处理?
- 可以想数据结构内添加元素
- 按照递增或递减的顺序排序
- 可以按顺序取出元素 由此想到递增或递减的话可以同栈实现,我们称之为单调栈,我们可以通过单调栈的方式来实现,用来存储最大的元素 3 ,栈顶保存的是当前的最大值因为我们是递减的单调栈,如果存在比栈顶元素还大的数,那么就弹出栈顶,知道不大于为止 这是栈存储的也就是最大的 3 元素,我们最后一次弹出的就是最大值的2元素,如果当前的 i 小 这个 2 元素 那么就可以认为 i 是最小的 1 元素。 此时132模式成立。
依次搞定a b c (b>c>a) b很好确定,nums[i]就是b a在b左边,a比bc小,所以a越小越好,a取最小值 c在b右边,要保证c比a大,所以c要是有序的,用一个优先队列存储b右边的所有数,
从右侧遍历数组,我们期望队列c中的所有数比a大, 去除所有比a小的数之后,peek的值就是比a大的最小c, 若此时最小c比b小即可满足条件,否则所有c都都不满足,继续向左遍历。
代码实现
public boolean find132pattern(int[] nums) {
int len = nums.length;
if (len < 3) return false;
int[] leftMin = new int[len];
leftMin[0] = nums[0];
for (int i = 1; i < len; i++) {
leftMin[i] = Math.min(leftMin[i - 1], nums[i - 1]);
}
PriorityQueue < Integer > rightQueue = new PriorityQueue < > ();
rightQueue.offer(nums[len - 1]);
for (int i = len - 2; i > 0; i--) {
int a = leftMin[i];
int b = nums[i];
while (!rightQueue.isEmpty() && rightQueue.peek() <= a) {
rightQueue.poll();
}
if (!rightQueue.isEmpty()) {
int c = rightQueue.peek();
if (a < c && c < b) return true;
}
rightQueue.offer(b);
}
return false;
}
运行结果
复杂度分析
- 空间复杂度:O(1)
- 时间复杂度:O(n)
在掘金(JUEJIN) 一起分享知识, Keep Learning!