Google算法题:132模式

题目


Given a sequence of n integers a1, a2, ..., an, a 132pattern is a subsequence ai, aj, ak such that i < j < kand ai < ak < aj. Design an algorithm that takes a list of n numbers as input and checks whether there is a 132 pattern in the list.

n will be less than 20,000.

样例

Given nums = [1, 2, 3, 4]
return False // There is no 132 pattern in the sequence.

Given nums = [3, 1, 4, 2]
return True // There is a 132 pattern in the sequence: [1, 4, 2].


题目来源:Link

LintCode链接:Link


分析


(1)方法一:利用最小值数组


TC = O(n)+ O(n^2)

SC = O(n)

1)遍历数组,对于 i,找到 0~i 中的小于 nums[i] 的最小值,存在 mins[i] 中,mins[i] 可能等于 nums [i], 这表明其右边没有比他更小的数,不影响后面的判断

2)从右往左遍历数组,维护一个list,里面是按照插入排序排列的,找到小于当前元素的最大值 max,与 min[i] 比较,若 max > mins[i],则找到了一个132


(1)方法二:利用栈


TC = O(n)

SC最坏:O(n)

SC最好:O(1)

1)用 knum 标记 k 代表的值(132模式中的2),Stack 里面存的是遍历到当前位置所有大于 knum的值(相当于132模式中的3),遍历的当前值(相当于132模式中的1),若nums[i] < knum 则表示发现了132

2)遍历过程中,如果当前小于栈顶,则压栈,如果大于栈顶,证明发现了比当前 knum 对应的 “3” 模式更大的数,则 pop 到 nums[i] < stack.peek(),pop的值赋值给knum,就是小于当前 nums[i] 右边的最大值(栈中的元素自顶向下是递减的)

3)有一种可能是 nums[i] 右边小于他的最大值,之前就被弹出,但是不要紧,由于栈里面放的是比当前 knum 大的数,且可定是连续递增的,若遍历中遇到了比栈顶更大的数,更新的 knum可定是比之前的更大,num[i] 都没有机会找自己的 knum,因为既然他的右边小于他的最大值都已经弹出,证明栈里面的都比他大,他只能被放进栈里面。

4)在132模式中,若2模式代表3模式的右边小于3模式的最大,若1模式代表3模式的左边小于3模式的最小,则1模式与2模式之间最大的3模式可定囊括其他3模式,而此方法就是向最大3模式逼近


代码


(1)方法一


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) {
        if(nums==null) return false;
        int n = nums.length;
        if(n<3) return false;
        
        int[] mins = new int[n];
        mins[0] = nums[0];
        for(int i=1; i s = new Stack();
        for(int i=n-1; i>-1; i--){
            while(!s.isEmpty() && nums[i]mins[i])
                    return true;
                s.add(nums[i]);
            }
        }
        return false;
    }
}


(2)方法二

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) {
    
        if(nums == null) return false;
        int n = nums.length;
        if(n<3) return false;
        
        Stack s = new Stack();
        int knum = Integer.MIN_VALUE;
        for(int i=n-1; i>=0; i--){
            if(nums[i]s.peek()){
                knum = s.pop();
            }
            s.add(nums[i]);
        }
        return false;
    }
}




你可能感兴趣的:(技巧题型,LintCode,Google,堆栈,Medium)