456. 132 模式
题目描述
给你一个整数数组 \(nums\) ,数组中共有 \(n\) 个整数。
132 模式的子序列 由三个整数 \(nums[i]\)、\(nums[j]\) 和 \(nums[k]\) 组成,并同时满足:\(i < j < k\) 和 \(nums[i] < nums[k] < nums[j]\) 。
如果 \(nums\) 中存在 132 模式的子序列 ,返回 \(true\) ;否则,返回 \(false\) 。
示例 1:
1 2 3 |
|
示例 2:
1 2 3 |
|
示例 3:
1 2 3 |
|
提示:
- \(n\) \(=\) \(nums.length\)
- \(1\) \(≤\) \(n\) \(≤\) \(2 * 10^5\)
- \(-10^9\) \(≤\) \(nums[i]\) \(≤\) \(10^9\)
算法与思路
(单调栈) \(O(n)\)
我们可以来考虑把每个数当成 132 模式的子序列 中 1
的情况,记为 \(a[i]\) ,当且仅当存在两个数 \(a[j], a[k]\),满足 \(i < j < k\),\(a[j] > a[k] > a[i]\) 时,132 模式的子序列 存在。
在满足以上 充要条件 中得出 \(a[j]\) 与 \(a[k]\) 是 单调递减 的。
在单调栈中,从栈底到栈顶的元素是严格单调递减的。当给定阈值 \(x\) 时,我们只需要不断地弹出栈顶的元素,直到栈为空或者 \(x\) 严格小于栈顶元素。此时我们再将 \(x\) 入栈,这样就维护了栈的单调性。
因此可以维护一个单调栈来判断当前 \(a[i]\) 是否满足条件。
- 维护 \(a[j], a[k]\) 的单调栈操作可以 从右往左 遍历数组,每次判断当前数是否 小于 \(a[k]\)。
- 为了方便起见,可以定义一个 \(right\) 来记录当前数为 \(a[i]\) 的情况下,\(a[k]\) 的最大值。
- 若满足条件,返回 \(true\);
- 若不满足,继续进行下列操作。
- 如果栈顶元素 小于 当前数 \(a[i]\),弹出栈顶元素,直到栈顶元素 大于 当前数 \(a[i]\)。
- 将当前数 \(a[i]\) 插入栈内,继续遍历下一个数,直到遍历完这个数组,返回 \(false\)。
复杂度分析
时间复杂度:O(n)。枚举 \(i\) 的次数为 \(O(n)\),由于每一个元素最多被加入和弹出单调栈各一次,因此操作单调栈的时间复杂度一共为 \(O(n)\),总时间复杂度为 \(O(n)\)。
空间复杂度:\(O(n)\),即为单调栈需要使用的空间。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|