版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjucor/article/details/82147795
Given a sequence of n integers a1, a2, ..., an, a 132 pattern is a subsequence ai, aj, ak such that i < j < k and 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.
Note: n will be less than 15,000.
Example 1:
Input: [1, 2, 3, 4]
Output: False
Explanation: There is no 132 pattern in the sequence.
Example 2:
Input: [3, 1, 4, 2]
Output: True
Explanation: There is a 132 pattern in the sequence: [1, 4, 2].
Example 3:
Input: [-1, 3, 2, 0]
Output: True
Explanation: There are three 132 patterns in the sequence: [-1, 3, 2], [-1, 3, 0] and [-1, 2, 0].
如果是123pattern,左右2边分别找最大最小就好了,但是这里是132pattern,就是23部分反过来了,比较容易想到用stack也反过来,但是貌似思路还不是很明显
正解:把s2,s3放在一起考虑,每次出现s2>s3的pair就更新s3可能的最大值,这样只需要出现s1<s3就可以判断存在132pattern了。那剩下的问题就是怎么更新s3可能的最大值呢?把s3可能达到的最大值放到stack里,没来一个s2就从stack中pop出比s2小的数,求pop过程最大的数即可
import java.util.TreeMap;
class Solution {
public boolean find132pattern(int[] nums) {
int n = nums.length;
if(n < 3) return false;
int min = nums[0];
TreeMap<Integer, Integer> s = new TreeMap<Integer, Integer>();
for(int i=2; i<n; i++) s.put(nums[i], s.containsKey(nums[i])?1+s.get(nums[i]):1);
for(int i=1; i<n-1; i++) {
if(nums[i] > min) {
Integer t = s.ceilingKey(min+1);
if(t != null && t < nums[i]) return true;
} else {
min = nums[i];
}
s.put(nums[i+1], s.get(nums[i+1])-1);
if(s.get(nums[i+1]) == 0) s.remove(nums[i+1]);
}
return false;
}
}
class Solution:
def find132pattern(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
if len(nums)<3: return False
s3_max=float('-inf')
st=[]
for i in nums[::-1]:
if s3_max>i: return True
while st and i>st[-1]:
s3_max=max(s3_max, st.pop())
st.append(i)
return False
https://leetcode.com/problems/132-pattern/discuss/94071/Single-pass-C++-O(n)-space-and-time-solution-(8-lines)-with-detailed-explanation.