Leetcode 456题:132模式题解

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

题解

首先,考虑边界条件:如果数组中的个数小于3个,那么不可能出现132模式,直接返回False。
其次,这道题的暴力解法便是穷举给定数组所能构成的所有三元组,然后验证每一个三元组是否满足132模式,如果找到一个三元组满足条件,则返回True,否则返回False。穷举法的时间复杂度为O(N^3)。

接下来讲一下这道题比较机智的做法。首先规定一下术语,我们把132模式中最大的数叫做大数(也就是3的位置),最小的数叫做小数(也就是1的位置),剩下2的位置我们称为次大数。其次规定一下算法中使用到的变量:一个变量third用于记录次大数,一个栈stack用于记录所有可能的大数,并且stack中的数和次大数都要尽可能的大(也就是stack中的数要在已知数中尽量大,而次大数要仅次于stack中的最小数)。

规定完成之后,我们从后往前遍历整个数组(假设有一个指针从后往前指过每一个数):
1)如果当前(指针指的)数比third小,我们有当前数、stack中栈顶元素和third组成132模式,目标达成,返回True;
2)如果当前数比stack栈顶元素要大,说明stack中有些数已经过时了,需要退出栈顶元素,继续比较直到栈顶元素大于当前数,将当前数入栈同时令third等于最后一次pop出的数。(实际上,stack栈记录了已经遍历的数中从大到小排列,而third则是已遍历数中除去stack栈中元素的最大值,即遵循了次大数尽可能大的规定。)
3)若当前数不符合上述两个条件,也就是当前数没有third小,但是也没有stack栈顶元素大,那么他有当次大数third)的潜质,我们把当前数放入stack栈中。
整个数组遍历完成后,若没有找到符合条件的132模式数组(即从未return过),则该数组中不存在132模式的数组,返回False。
注:之所以使用栈存储可能的大数,是为了保证大数一定在次大数的左侧。(靠左的数后入栈,也就越靠栈顶)

Python代码

class Solution(object):
    def find132pattern(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        
        if len(nums)<=2:
            return False
        third = float('-inf')
        stack = []
        for i in range(len(nums)-1,-1,-1):
            if nums[i]<third:
                return True
            else:
                while stack and stack[-1] < nums[i]:
                    third = stack.pop()
            stack.append(nums[i])
        return False
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值