力扣每日一题:456. 132模式

题目:456. 132模式

难度: 中等

题目
给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[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] 。

提示

  • n == nums.length
  • 1 <= n <= 104
  • -109 <= nums[i] <= 109

来源:力扣(LeetCode)
链接https://leetcode-cn.com/problems/132-pattern
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。



解题思路

(1)暴力破解

  在一系列nums中找到132模式的数,也就是说:1是最小的,3是中间的也是最大的,2比1大但比3小。如果直接强行解,那么循环3次,分别遍历1、3、2,恭喜你:时间复杂度O(n^3),直接超时。
  当然如果我们控制一个变量,遍历两个数,还是可以做到O(n^2),也算暴力破解了。比较好的想法是控制3先遍历3,也就是中间的最大的数。那么1必然在3左边的且小于3小于2,那么1可以取3左边最小的就肯定不会错了。而后再遍历2,在3的最左边,只要3>2且2>1,那么肯定3>2>1。

(2)单调栈

  可以用一个栈存储3,一个变量max2记录2的最大值,从尾部到头遍历1,直到找到小于max2的数,就找到132模式数。实现单调栈时,如果当前元素大于栈顶,不断弹出栈中元素,并记录小于当前元素的最大值,然后再讲当前元素压栈,这时就保证了3>2,只要在找到2>1就找到132模式数了。

解题代码

(1)暴力破解

class Solution {
public:
    bool find132pattern(vector<int>& nums) {

        int n = nums.size();
        int num1 = nums[0];//132模式中的1,即最小的数
        for(int i = 1; i < n - 1; i++)//该处遍历3,即中间的数,也是最大的数
        {
            for(int j = n - 1;j > i; j--)
            {
                if(nums[j] > num1 && nums[i] > nums[j])// 3>2 2>1 则:2 > 3 > 1
                    return true;
            }
            num1 = num1 < nums[i] ? num1 : nums[i]; 
        }
        return false;
    }
};

(2)单调栈

class Solution {
public:
    bool find132pattern(vector<int>& nums) {

        stack<int> stk;//单调栈,存入的数据为3
        int max2 = INT_MIN;//2的最大值,越大越容易找到1
        int n = nums.size();
        stk.push(nums[n - 1]);//压入最后一个数,从尾到头遍历
        for(int i = n - 1; i >= 0; i--)//此处遍历1
        {
            if(nums[i] < max2)//如果2>1,之前已经满足3>2了
            {
                return true;
            }

            while(!stk.empty() && nums[i] > stk.top())
            {
                max2 = stk.top();//存储2的最大值
                stk.pop();
            }
            if(nums[i] > max2)
                stk.push(nums[i]);

        }
        return false;
    }
};

解题感悟

  该题难度有点大,特别是单调栈,不看题解写不出。。。写完单调栈,倒是有些许感悟:首先,要有贪心的思想,毕竟只是找到是否有132模式的数而非找到所有的数,因此要大胆。接着,很明显3个变量,比较难控制。但是用一个栈加一个变量,就实现了一次遍历保证3>2,这时候只要2>1即可,因此再在下次进入时判断就完成了。还有就是从后往前遍历,因为3和2是最大和次大,比较好维护。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗夜无风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值