# 456.132模式

## 问题描述
[456. 132 模式 (Medium)](https://leetcode.cn/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` 。
**示例 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 <= 2 * 10⁵`
- `-10⁹ <= nums[i] <= 10⁹`

## 解题思路
枚举`i`，找到符合条件的`(j, k)`，贪心想法，`nums[k]`必定是满足`j > k`且`nums[k] < nums[j]`的所有`nums[k]`中最大的一个，因此这里我们采用单调栈来模拟寻找`(j, k)`的过程，考虑到`k > j`，这里需要从后往前遍历。

记`first = nums[i], second = nums[j], third = -INT_MAX`，栈为单调递减的（考虑入栈顺序），即栈底到栈顶单调递减，从后往前遍历数组：
- 如果栈为空，就入栈，不更新`third`；
- 如果将要入栈的元素大于栈顶元素，那就将栈顶元素弹出（如果栈顶元素大于`third`，更新`third`），直到栈为空或者要将入栈的元素小于栈顶元素；
- 如果将要入栈的元素小于栈顶元素，那么比较该元素和`third`的大小，如果该元素小于`third`，说明找到了三元组，否则将该元素入栈

本题的关键我认为有三个，一是想到枚举`i`找`(j, k)`，二是找最大的`nums[k]`，三是从后往前遍历。

## 代码
```cpp
class Solution {
  public:
    bool find132pattern(vector<int> &nums) {
        int first = nums[0], second = nums[nums.size() - 1], third = -INT_MAX;
        int i = 0;
        stack<int> stk; // 栈顶到栈底从小到大
        stk.push(nums[nums.size() - 1]);
        for (int r = nums.size() - 2; r >= 0; r--) {
            // 栈应该不可能为空
            if (nums[r] < stk.top()) {
                // if (stk.top() > third) {
                if (nums[r] < third) {
                    return true;
                    // }
                }
                stk.push(nums[r]);
            } else if (nums[r] == stk.top()) {
                stk.push(nums[r]);
            } else {
                while (!stk.empty() && nums[r] > stk.top()) {
                    third = std::max(stk.top(), third);
                    stk.pop();
                }
                stk.push(nums[r]);
            }
        }
        return false;
    }
};
```
