提交 92cf4be2 编写于 作者: L lucifer

feat: 456

上级 211404e2
......@@ -330,6 +330,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
- [0424. 替换后的最长重复字符](./problems/424.longest-repeating-character-replacement.md)
- [0445. 两数相加 II](./problems/445.add-two-numbers-ii.md)
- [0454. 四数相加 II](./problems/454.4-sum-ii.md)
- [0456. 132 模式](./problems/456.132-pattern.md) 🆕
- [0464. 我能赢么](./problems/464.can-i-win.md)
- [0494. 目标和](./problems/494.target-sum.md)
- [0516. 最长回文子序列](./problems/516.longest-palindromic-subsequence.md)
......
......@@ -182,6 +182,7 @@
- [0424. 替换后的最长重复字符](./problems/424.longest-repeating-character-replacement.md) 🆕
- [0445. 两数相加 II](./problems/445.add-two-numbers-ii.md)
- [0454. 四数相加 II](./problems/454.4-sum-ii.md)
- [0456. 132 模式](./problems/456.132-pattern.md) 🆕
- [0464. 我能赢么](./problems/464.can-i-win.md)
- [0494. 目标和](./problems/494.target-sum.md)
- [0516. 最长回文子序列](./problems/516.longest-palindromic-subsequence.md)
......
## 题目地址(456. 132 模式)
https://leetcode-cn.com/problems/132-pattern/
## 题目描述
```
给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[i] < nums[k] < nums[j] 。
如果 nums 中存在 132 模式的子序列 ,返回 true ;否则,返回 false 。
 
进阶:很容易想到时间复杂度为 O(n^2) 的解决方案,你可以设计一个时间复杂度为 O(n logn) 或 O(n) 的解决方案吗?
 
示例 1:
输入:nums = [1,2,3,4]
输出:false
解释:序列中不存在 132 模式的子序列。
示例 2:
输入:nums = [3,1,4,2]
输出:true
解释:序列中有 1 个 132 模式的子序列: [1, 4, 2] 。
示例 3:
输入:nums = [-1,3,2,0]
输出:true
解释:序列中有 3 个 132 模式的的子序列:[-1, 3, 2]、[-1, 3, 0] 和 [-1, 2, 0] 。
 
提示:
n == nums.length
1 <= n <= 104
-109 <= nums[i] <= 109
```
## 前置知识
- [单调栈](../thinkings/monotone-stack.md) 🆕
## 公司
- 暂无
## 思路
132 模式指的是满足:大小关系是 1 < 2 < 3 ,索引关系是 1 < 3 < 2 的三个数。
一个简单的思路是使用一层**从左到右**的循环固定 3,遍历的同时维护最小值,这个最小值就是 1(如果固定的 3 不等于 1 的话)。 接下来使用另外一个嵌套寻找枚举符合条件的 2 即可。 这里的符合条件指的是大于 1 且小于 3。这种做法的时间复杂度为 $O(n^2)$,并不是一个好的做法,我们需要对其进行优化。
实际上,我们也可以枚举 2 的位置,这样目标变为找到一个大于 2 的数和一个小于 2 的数。由于 2 在序列的右侧,因此我们需要**从右往左**进行遍历。又由于题目只需要找到一个 312 模式,因此我们应该贪心地选择尽可能大的 2(只要不大于 3 即可),这样才**更容易找到 1**(换句话说不会错过 1)。
首先考虑找到 32 模式。我们可以使用从右往左遍历,遇到一个比后一位大的数。我们就找到了一个可行的 32 模式。和上面思路类似,维护一个全局最小值即可,这样就不会错过答案。可是这样就无法做到前面提到的**贪心地选择尽可能大的 2**,我们选择的 2 实际上是尽可能小的 2。那如何找到尽可能大的并且比当前数小的 2 呢?
其实,我们可以维护一个递增栈。每次遇到一个比栈顶大的数就 pop 栈,直到栈顶比当前数字还大。那么最后一次 pop 出去的就是满足条件的最大的 2 了。找到了 32 模式,接下来,我们只需要找到一个比 2 小的数就可以直接返回 True 了。
## 关键点
- 固定 2, 从右往左遍历,使用单调栈获取最大的小于当前数的 2,并将当前数作为 3 。
## 代码
- 语言支持:Python3
Python3 Code:
```python
class Solution:
def find132pattern(self, nums: List[int]) -> bool:
s2, stack = float("-inf"), []
for i in range(len(nums) - 1, -1, -1):
if nums[i] < s2:
return True
while stack and stack[-1] < nums[i]:
s2 = stack.pop()
stack.append(nums[i])
return False
```
**复杂度分析**
令 n 为数组长度。
- 时间复杂度:$O(n)$
- 空间复杂度:$O(n)$
> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册