小彩笔的痛苦刷题日记 ——132模式

题目:
  给定一个整数序列:a1, a2, …, an,一个132模式的子序列 ai, aj, ak 被定义为:当 i < j < k 时,ai < ak < aj。设计一个算法,当给定有 n 个数字的序列时,验证这个序列中是否含有132模式的子序列。
注意:n 的值小于15000。

示例1:
输入: [1, 2, 3, 4]
输出: False
解释: 序列中不存在132模式的子序列。

示例 2:
输入: [3, 1, 4, 2]
输出: True
解释: 序列中有 1 个132模式的子序列: [1, 4, 2].

示例 3:
输入: [-1, 3, 2, 0]
输出: True
解释: 序列中有 3 个132模式的的子序列: [-1, 3, 2], [-1, 3, 0] 和 [-1, 2, 0].
  • 我检讨,我太蠢了,审题一点都不清楚,一看开始做没注意示例三,只看了前两个示例,我还沾沾自喜,然后我写完发现通过不了我才搞懂原来是要求子序列,哎~又是子序列的题,怎么做…不知道…该不会是动态规划吧…
  • 犯蠢写的代码也放上,我是傻X;
class Solution {
    // 遍历n这数组,定义三个指针
    // i指向第一个
    // j指向第二个
    // k指向第三个
    // 如果nums[i]<nums[j] && nums[j]>nums[k] 则返回true
    // 每次i,j,k均+1
    public boolean find132pattern(int[] nums) {
        int i=0;
        int j=1
        int k=2;
        while(k < nums.length){
            if(nums[i] < nums[j] && nums[j] > nums[k] && nums[i] < nums[k]){
                return true;
            }
            i++;
            j++;
            k++;
        }
        return false;
    }
}
  • 所以这题咋解…
  • 根据之前做的子序列的问题,我想到了动态规划…太难…想起动态规划就头大
  • 既然求是否有132这种类型
  • 既然是动态规划,那我先找出到每个位置最小的数 min[i]
    min[0] = nums[0]第一个位置前最最小的是它自己
    for(int i = 1; i < nums.length; i++) min[i] = Math.min(nums[i-1],nums[i]);
  • 我放弃了,看答案去了
  • 好吧,用栈存放,大家都好厉害,我是废物
  • 逆序从后往前遍历nums[] 数组,如果nums[i]大于min[i]则开始进行判断入栈等操作,否则跳过当前i
  • 如果nums[i]大于min[i],看栈不为空且栈顶元素是否小于或等于min[i],如果小于或等于,则说明栈顶不符合132中的2,肯定不是 a k a_k ak,弹出栈顶
  • 如果栈不为空且栈顶元素小于nums[i],说明符合132,返回true
  • 不满足上述两条件,将当前nums[i]入栈
class Solution {
    // 用minimal[i]表示从0到i最小的数
    // 用一个栈逆序遍历原数组,栈维护的是大于minimal[i]且小于nums[i]的元素
    public boolean find132pattern(int[] nums) {
        int n = nums.length;
        int[] min = new int[n];
        min[0] = nums[0]; // 第一个位置及它之前的最小数使它自己
        // 遍历nums数组,比较i下标及以前的数最小的放在min[i]位置
        for(int i = 1; i < n; i++){ //零位置的最小值就是它自己,从1位置开始和0位置对比
            min[i] = Math.min(min[i-1], nums[i]);
        }
        // 从后往前遍历,将i位置到n-1位置中,大于min[i]且小于nums[i]的数放进栈
        Stack<Integer> stack = new Stack<>();
        for(int i = n-1; i >=0; i--){
            if(nums[i] > min[i]){
                // 逆序从数组最后一个元素往前走,min[i]下标存放的是在nums数组中0-i位置的最小数
                // nums[i]都比min[i]小了或者相等,则这个数肯定不是子序列的,跳过这个数
                while(!stack.isEmpty() && stack.peek() <= min[i]){
                    stack.pop(); 
                }
                if(!stack.isEmpty() && stack.peek() < nums[i]){
                    return true;
                }
                stack.push(nums[i]);
            }
        }
        return false;
    }
}
输入以nums = [-1, 3, 2, 0, 4, -1, 1]为例
1、首先遍历数组后得到 min数组 min = [-1, -1, -1, -1, -1, -1, -1];
2、从后往前遍历nums数组,nums[6] > min[6],是栈里为空,所以执行stack.push(nums[6]),将nums[6]=1放入栈
3、nums[5] > min[5] 不成立;i--
4、nums[4] > min[4],while条件不通过,if条件执行,返回true;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值