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].
/**************************************************/
题目的分类是栈,但是我一开始没搞懂和栈有什么关系,所以我一开始是用很naive的方法去实现的:
- naive的方法很简单,就是跑两次O(n*n)的循环,找到每个点对应的最远的较小点以及最近的较大点。显然只要任意点最远较小点 比 最近较大点远,那么就符合题目要求的132pattern了。时间复杂度是O(n*n),在LeetCode用时排在后40%。
- 学习了一下前10%的代码,原来使用栈可以让问题变得更简单:从数组后面向前遍历,用栈暂时存下所有没有遇到比自身值更大的值的点,用另一个临时变量temp存放当前已经遇到了更大值的点中的最大值。只要遍历过程中遇到比temp小的值,那么就说明一定存在一个132pattern。显然这种方法只需要O(n)时间复杂度,快了很多。
最后放一下我的方法的代码:
class Solution {
public boolean find132pattern(int[] nums) {
int FarthestLess[] = new int[nums.length];
int NearestLarger[] = new int[nums.length];
for(int i = 2;i<nums.length;i++)
{
FarthestLess[i] = -1;
NearestLarger[i] = -1;
for(int j = 0;j<=i/2;j++)
{
if(nums[j]<nums[i])
{
FarthestLess[i] = j;
break;
}
}
for(int j = i-1;j>0 && j>FarthestLess[i];j--)
{
if(nums[j]>nums[i])
{
NearestLarger[i] = j;
break;
}
}
}
for(int i = 2;i<nums.length;i++)
{
if(FarthestLess[i]!= -1 && NearestLarger[i]!=-1 && FarthestLess[i]<NearestLarger[i])
return true;
}
return false;
}
}