题目:
给定一个整数序列: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].
- 我检讨,我太蠢了,审题一点都不清楚,一看开始做没注意示例三,只看了前两个示例,我还沾沾自喜,然后我写完发现通过不了我才搞懂原来是要求子序列,哎~又是子序列的题,怎么做…不知道…该不会是动态规划吧…
- 犯蠢写的代码也放上,我是傻X;
class Solution {
// 遍历n这数组,定义三个指针
// i指向第一个
// j指向第二个
// k指向第三个
// 如果nums[i]<nums[j] && nums[j]>nums[k] 则返回true
// 每次i,j,k均+1
public boolean find132pattern(int[] nums) {
int i=0;
int j=1
int k=2;
while(k < nums.length){
if(nums[i] < nums[j] && nums[j] > nums[k] && nums[i] < nums[k]){
return true;
}
i++;
j++;
k++;
}
return false;
}
}
- 所以这题咋解…
- 根据之前做的子序列的问题,我想到了动态规划…太难…想起动态规划就头大
- 既然求是否有132这种类型
- 既然是动态规划,那我先找出到每个位置最小的数 min[i]
min[0] = nums[0]
第一个位置前最最小的是它自己
for(int i = 1; i < nums.length; i++) min[i] = Math.min(nums[i-1],nums[i]);
- 我放弃了,看答案去了
- 好吧,用栈存放,大家都好厉害,
我是废物 - 逆序从后往前遍历
nums[]
数组,如果nums[i]
大于min[i]
则开始进行判断入栈等操作,否则跳过当前i
- 如果
nums[i]
大于min[i]
,看栈不为空且栈顶元素是否小于或等于min[i]
,如果小于或等于,则说明栈顶不符合132中的2,肯定不是 a k a_k ak,弹出栈顶 - 如果栈不为空且栈顶元素小于
nums[i]
,说明符合132,返回true
- 不满足上述两条件,将当前nums[i]入栈
class Solution {
// 用minimal[i]表示从0到i最小的数
// 用一个栈逆序遍历原数组,栈维护的是大于minimal[i]且小于nums[i]的元素
public boolean find132pattern(int[] nums) {
int n = nums.length;
int[] min = new int[n];
min[0] = nums[0]; // 第一个位置及它之前的最小数使它自己
// 遍历nums数组,比较i下标及以前的数最小的放在min[i]位置
for(int i = 1; i < n; i++){ //零位置的最小值就是它自己,从1位置开始和0位置对比
min[i] = Math.min(min[i-1], nums[i]);
}
// 从后往前遍历,将i位置到n-1位置中,大于min[i]且小于nums[i]的数放进栈
Stack<Integer> stack = new Stack<>();
for(int i = n-1; i >=0; i--){
if(nums[i] > min[i]){
// 逆序从数组最后一个元素往前走,min[i]下标存放的是在nums数组中0-i位置的最小数
// nums[i]都比min[i]小了或者相等,则这个数肯定不是子序列的,跳过这个数
while(!stack.isEmpty() && stack.peek() <= min[i]){
stack.pop();
}
if(!stack.isEmpty() && stack.peek() < nums[i]){
return true;
}
stack.push(nums[i]);
}
}
return false;
}
}
输入以nums = [-1, 3, 2, 0, 4, -1, 1]为例
1、首先遍历数组后得到 min数组 min = [-1, -1, -1, -1, -1, -1, -1];
2、从后往前遍历nums数组,nums[6] > min[6],是栈里为空,所以执行stack.push(nums[6]),将nums[6]=1放入栈
3、nums[5] > min[5] 不成立;i--
4、nums[4] > min[4],while条件不通过,if条件执行,返回true;