利用单调栈查找数组中【132模式的子序列】

104 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

题目描述

给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]nums[j]nums[k] 组成,并同时满足:i < j < knums[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 * 105^5
  • -109^9 <= nums[i] <= 109^9

单调栈

我们可以利用栈后进先出的特性来保存遍历过的元素,当遇到比栈顶元素还大的数值时,我们需要将其从栈顶弹出,复制给 132中的2,再将新的数值入栈,到了这里,我们132中的32已经有了,如果在接下来的遍历在,发现有比2更小的数值,即表示该条件满足,直接返回结果。否则重复前面的比较步骤,直至遍历完整个数组。 Kapture 2022-04-17 at 21.10.26.gif

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;
    }
}