leetcode-456-132 模式

36 篇文章 1 订阅
28 篇文章 0 订阅
456. 132 模式

给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]nums[j]nums[k] 组成,并同时满足:i < j < knums[i] < nums[k] < nums[j]

如果 nums 中存在 132 模式的子序列 ,返回 true ;否则,返回 false

**进阶:**很容易想到时间复杂度为 O(n^2) 的解决方案,你可以设计一个时间复杂度为 O(n logn)O(n) 的解决方案吗?

示例 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] 。
枚举1

如果我们从左到右枚举 1 的下标 i,那么 j,k 的下标范围都是减少的,这样就不利于对它们进行维护。因此我们可以考虑从右到左枚举 i。

我们用单调栈维护所有可以作为 2 的候选元素。初始时,单调栈中只有唯一的元素 a[n−1]。我们还需要使用一个变量 maxK记录所有可以真正作为 2 的元素的最大值;

随后我们从 n−2开始从右到左枚举元素 a[i]

首先我们判断 a[i]是否可以作为 1。如果 a[i]<maxK,那么它就可以作为 1,我们就找到了一组满足 132模式的三元组;

随后我们判断 a[i] 是否可以作为 3,以此找出哪些可以真正作为 2 的元素。我们将 a[i] 不断地与单调栈栈顶的元素进行比较,如果 a[i] 较大,那么栈顶元素可以真正作为 2,将其弹出并更新 maxK;

最后我们将 a[i] 作为 2 的候选元素放入单调栈中。这里可以进行一个优化,即如果 a[i]≤maxK,那么我们也没有必要将 a[i] 放入栈中,因为即使它在未来被弹出,也不会将 maxK 更新为更大的值。
class Solution {
    public boolean find132pattern(int[] nums) {
        //记录数组长度
        int n = nums.length;
        //定义单调栈  在单调栈中,从栈底到栈顶的元素是严格单调递减的
        //使用单调栈维护2
        Deque<Integer> candidateK = new LinkedList<Integer>();
        //首先将a[n-1]入栈
        candidateK.push(nums[n - 1]);
        //将maxK初始化为最下值
        int maxK = Integer.MIN_VALUE;

        for (int i = n - 2; i >= 0; --i) {
            //第一轮进不来 ,进入选择时栈中最少有两个元素
            //找1
            if (nums[i] < maxK) {
                return true;
            }
            //如果栈不空,且nums[i]>栈中的最大元素,此时就认为当前栈顶作为2,就将栈清空  
            //然后在下面的选择中将当前元素维护为3
            //之后的任务就是找1
            while (!candidateK.isEmpty() && nums[i] > candidateK.peek()) {
                maxK = candidateK.pop();
            }
            if (nums[i] > maxK) {
                candidateK.push(nums[i]);
            }
        }

        return false;
    }
}
单调栈维持1,3
class Solution {
    public boolean find132pattern(int[] nums) {
    	//长度小于3,不符合直接返回false
        if(nums.length < 3){
            return false;
        }
        //定义smallest初值为最大值
        int smallest = Integer.MAX_VALUE;
        //定义单调栈  在单调栈中,从栈底到栈顶的元素是严格单调递减的
        //使用单调栈维护着1,3
        Deque<int[]> stack = new LinkedList<>();
        //遍历数组
        for(int num : nums){
            //第一轮就进来了 ,始终保持着当前元素比前面的最小元素大
            //而smallest维护着此次循环之前的最小元素,作为1
            if(num <= smallest){
                smallest = num;
                continue;
            }
            //栈非空 遍历栈
            while(!stack.isEmpty()){
                //获取栈顶
                int[] arr = stack.peek();
                //如果num>栈中维持的num(也就是3),此时栈中维持的数据已经不适合了,直接出栈
                if(num >= arr[1]){
                    stack.pop();
                    continue;
                }
                //如果num<栈中维持的num(也就是3),且num<smallest(也就是最小值) 此时达成 1 3 2
                if(arr[0] < num){
                    return true;
                }
                //如果本次栈顶的元素smallest>num则继续进行遍历获取最小值
                if(arr[0] >= num){
                    break;
                }
            }
            //将此次循环之前的最小值和一个大于最小值的数入栈
            //维护1,3
            stack.push(new int[]{smallest, num});
        }
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值