Problem Statement
(Source) 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].
Solution - java.TreeSet
The idea is to first construct a prefix-min array
(as I name it): left[i]
stores the minimal value from position 0
to i
(inclusive). Then scan the original array from end to start and check if all scanned elements contains some element x
that is larger than left[i]
but smaller than nums[i]
. If there exists such an element, return true. Otherwise, it will return false at the end.
Java TreeSet
comes very handy for this question :)
public class Solution {
public boolean find132pattern(int[] nums) {
int n = nums.length;
if (n < 3) {
return false;
}
int[] left = new int[n];
left[0] = nums[0];
for (int i = 1; i < n; i++) {
left[i] = left[i-1] > nums[i] ? nums[i] : left[i-1];
}
TreeSet<Integer> set = new TreeSet<>();
for (int i = n - 1; i >= 0; i--) {
set.add(nums[i]);
if (!set.headSet(nums[i], false).tailSet(left[i], false).isEmpty()) {
return true;
}
}
return false;
}
}
If using Python with the same idea, will get an TLE
:
class Solution(object):
def find132pattern(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
n = len(nums)
if n < 3:
return False
left = [nums[0]] * n
for i in xrange(1, n):
left[i] = min(left[i-1], nums[i])
st = set()
for i in xrange(n - 1, -1, -1):
st.add(nums[i])
if any(left[i] < x < nums[i] for x in st):
return True
return False