Given an array of n integers nums, a 132 pattern is a subsequence of three integers nums[i], nums[j] and nums[k] such that i < j < k and nums[i] < nums[k] < nums[j].
Return true if there is a 132 pattern in nums, otherwise, return false.
Example 1:
Input: nums = [1,2,3,4]
Output: false
Explanation: There is no 132 pattern in the sequence.
Example 2:
Input: nums = [3,1,4,2]
Output: true
Explanation: There is a 132 pattern in the sequence: [1, 4, 2].
判断数组中是否存在132模式,也就是存在i < j < k, 使nums[i] < nums[k] < nums[j]
也就是i, j, k下标,简称为第1,2,3个数,第1个数要比第3个数小,第3个数又比第2个数小。
思路:
要找到第2个数最大,同时第3个数 < 第2个数,但又比第1个数大。
所以理清这样的关系,
为了找到第3个数比第1个数大,最好找到大小仅次于第2个数的数字。
问题就转换为要得到仅仅小于目前得到的最大值的数。
用一个单调栈来解决,因为要找第3个数,所以从后往前遍历数组。
栈里比nums[i]小的全部取出,把nums[i]保存进去,
这样做就是只保留当前最大的元素,所以从栈中取出的最后一个元素就是之前最大的,也就是仅小于当前nums[i]的第3个数,nums[i]就是第2个数。
把第3个数字保存到last变量。
下一次遇到nums[i] < last,就说明找到了第1个数,它满足 < 第3个数的条件,而第3个数 < 第2个数的条件在保存进栈时就已经满足了。
public boolean find132pattern(int[] nums) {
int n = nums.length;
if(n < 3) return false;
Stack<Integer> st = new Stack<>();
int last = Integer.MIN_VALUE;
for(int i = n - 1; i >= 0; i--) {
if(nums[i] < last) return true;
while(!st.isEmpty() && nums[i] > st.peek()) last = st.pop();
st.push(nums[i]);
}
return false;
}
用当前数组nums和一个栈顶指针top来模拟栈,效率更高。
public boolean find132pattern(int[] nums) {
int n = nums.length;
if(n < 3) return false;
int top = n;
int last = Integer.MIN_VALUE;
for(int i = n - 1; i >= 0; i--) {
if(nums[i] < last) return true;
while(top < n && nums[i] > nums[top]) last = nums[top ++];
nums[--top] = nums[i];
}
return false;
}