【Lintcode】636. 132 Pattern

题目地址:

https://www.lintcode.com/problem/636/

给定一个长 n n n的数组 A A A,问是否存在 i < j < k i<j<k i<j<k使得 A [ j ] > A [ k ] > A [ i ] A[j]>A[k]>A[i] A[j]>A[k]>A[i]

A A A反序,那么问题就转化为是否存在 231 231 231的模式。思路是单调栈。我们枚举 1 1 1,那么对于每个 1 1 1,都要左边去找满足条件的 2 2 2 3 3 3,那么可以想象,如果找到尽可能大的满足条件的 2 2 2是最好的(“满足条件”指的是对于这个 2 2 2,后面存在 3 3 3,即存在比这个 2 2 2大的数。因为找到尽可能大的 2 2 2的话,就可以在枚举 1 1 1的时候获得最大的优势)。开一个变量 l l l记录每次循环枚举的数的左边的满足条件的最大的 2 2 2。开一个单调递减的栈,对于一个新的数 x x x,如果 x x x大于栈顶,说明栈顶 t t t可以作为将来的 2 2 2使用,则更新 l l l max ⁡ { l , t } \max\{l,t\} max{l,t}。也就是说,栈里存的是能作为最大的 2 2 2的备选数,而 l l l存的是当前循环开始的时候能作为最大的 2 2 2的数。详细来说,遍历到 A [ i ] A[i] A[i]的时候,如果一旦发现了 l > A [ i ] l>A[i] l>A[i],则说明找到了一个 231 231 231模式,返回true;否则考虑 l l l是否会被更新,如果栈顶小于 A [ i ] A[i] A[i]的话,说明栈顶 t t t可以作为 l l l,则用栈顶来更新 l l l为更大的数(如果 l l l自己更大那就不用变了),pop栈顶直到栈空或者栈顶大于等于 A [ i ] A[i] A[i],接着再把 A [ i ] A[i] A[i]进栈,因为 A [ i ] A[i] A[i]也有可能将来成为 2 2 2的一个选择。这样栈的确是单调下降的。代码如下:

import java.util.ArrayDeque;
import java.util.Deque;

public class Solution {
    /**
     * @param nums: a list of n integers
     * @return: true if there is a 132 pattern or false
     */
    public boolean find132pattern(int[] nums) {
        // write your code here
        reverse(nums);
        
        Deque<Integer> stk = new ArrayDeque<>();
        int left = Integer.MIN_VALUE;
        for (int i = 0; i < nums.length; i++) {
        	// 如果当前满足条件的2大于了nums[i],那就找到了231模式
            if (left > nums[i]) {
                return true;
            }
            
            // 更新可以作为2的最大数
            while (!stk.isEmpty() && stk.peek() < nums[i]) {
                left = Math.max(left, stk.pop());
            }
            
            stk.push(nums[i]);
        }
        
        return false;
    }
    
    private void reverse(int[] A) {
        for (int i = 0, j = A.length - 1; i < j; i++, j--) {
            int tmp = A[i];
            A[i] = A[j];
            A[j] = tmp;
        }
    }
}

时空复杂度 O ( n ) O(n) O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值