LeetCode-456. 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].

思路:
首先想到的是三层循环暴力解,不过这肯定超时。
1.我们可以固定最大的aj,然后就可以确定最小的ai,ai取序列a1…aj的最小值,这样可以使ak的取值范围更大,但是必须满足nums[j]>min[j], min[j]代表ai取序列a1…aj的最小值。
2.aj从右往左遍历,aj和ai固定好了,接下来就确定ak,ak需要满足的条件是:ak>mid[j],ak的取值在j后面的数。
3.如果每次固定了aj和ai后都一一比较ak>ai,复杂度很高。所以我们引入了栈来优化。因为aj从右往左,ak必须是满足了nums[j]>min[j]的nums[j],所以我们用栈来存储nums[j],用于ak的取值。
代码:

class Solution {
    public boolean find132pattern(int[] nums) {
        if (nums.length < 3) {
            return false;
        }

        //计算0--j的最小值
        int[] min = new int[nums.length];
        min[0] = nums[0];
        //min[j]代表的是0-j的最小值
        for (int i = 1; i < nums.length; i++) {
            min[i] = Math.min(min[i-1],nums[i]);
        }

        Stack<Integer> stack = new Stack<>();
        //从右完左遍历j
        for (int j = nums.length - 1; j >0; j--) {
            if (nums[j] > min[j]) {
            	//比当前的最小值要小出栈,
                while(!stack.isEmpty() && stack.peek() < min[j]) {
                    stack.pop();
                }
                //栈顶元素不为空,说明大于ak大于最小值。只要在满足小于nums[j]则满足条件
                if (!stack.isEmpty() && stack.peek() < nums[j]) {
                    return true;
                } 
                //进栈
                stack.push(nums[j]);
            }
        }

        return false;

    }
}
发布了84 篇原创文章 · 获赞 50 · 访问量 7055

猜你喜欢

转载自blog.csdn.net/qq_43115606/article/details/103374479