LeetCode 456 - 132 模式


文章目录

摘要

LeetCode 456 是一道乍一看很绕,但想通后非常优雅的题。

很多人第一次读题时,脑子里会立刻冒出三层循环:

i < j < k,再判断 nums[i] < nums[k] < nums[j]

但很快你就会发现,这样做在数据量稍微大一点时,根本跑不动。

这道题真正考的是:

你能不能把"132 关系"转换成一种顺序扫描 + 单调结构的问题。

一旦理解了这一点,这题就会从"看不懂"变成"非常巧"。

描述

题目给你一个整数数组 nums,让你判断数组中是否存在一种特殊的子序列,叫 132 模式

什么是 132 模式?

存在三个下标 i < j < k,满足:

复制代码
nums[i] < nums[k] < nums[j]

也就是说:

  • 第一个数最小
  • 第二个数最大
  • 第三个数夹在中间

只要存在任意一组,直接返回 true,否则返回 false

题解答案(整体思路)

为什么这题不适合正着想?

如果你从左往右去想:

  • 固定 j
  • 去左边找最小的 i
  • 再去右边找合适的 k

你会发现状态太多,逻辑也很难压缩。

这道题真正舒服的解法是:

从右往左看,用栈维护"可能成为 3 的值",同时动态记录"可能成为 2 的最大值"。

核心思路一句话版

  • 从右向左遍历数组
  • 用一个单调递减栈保存"可能的 3(nums[j])"
  • 用一个变量 third 记录"已经找到的最大 nums[k]"
  • 一旦发现 nums[i] < third,说明 132 成立

题解答案(Swift 可运行 Demo)

swift 复制代码
class Solution {
    func find132pattern(_ nums: [Int]) -> Bool {
        if nums.count < 3 { return false }
        
        var stack: [Int] = []
        var third = Int.min
        
        // 从右往左遍历
        for num in nums.reversed() {
            // 如果当前数比 third 小,说明找到了 132
            if num < third {
                return true
            }
            
            // 维护单调递减栈
            while let last = stack.last, num > last {
                third = last
                stack.removeLast()
            }
            
            stack.append(num)
        }
        
        return false
    }
}

题解代码分析

这段代码短,但信息密度非常高,我们一步一步拆。

1. 为什么要从右往左?

swift 复制代码
for num in nums.reversed() {

原因很关键:

  • 我们希望先确定 nums[j]nums[k]
  • 再回头看有没有更小的 nums[i]

如果你从左往右,很难"记住未来的信息"。

2. 栈里存的到底是什么?

swift 复制代码
var stack: [Int] = []

这个栈里存的是:

还没被淘汰的、可能作为 nums[j](3 的位置)的值

而且这个栈始终保持 单调递减

3. third 是干嘛的?

swift 复制代码
var third = Int.min

third 表示:

目前已经确认的,最大可能的 nums[k](2 的位置)

它来自哪里?

swift 复制代码
while let last = stack.last, num > last {
    third = last
    stack.removeLast()
}

当你发现当前数 num 比栈顶大时:

  • 说明 num 可以作为更大的 3
  • 被弹出的那个数,就成了"被夹在中间的 2"

4. 核心判断为什么是这样?

swift 复制代码
if num < third {
    return true
}

此时的含义是:

  • 当前 numnums[i]
  • third 是已经找到的 nums[k]
  • 而之前一定存在一个更大的 nums[j]

自然满足:

复制代码
nums[i] < nums[k] < nums[j]

132 模式成立。

示例测试及结果

示例 1

swift 复制代码
let solution = Solution()
print(solution.find132pattern([1,2,3,4]))

输出:

text 复制代码
false

解释:

  • 数组严格递增
  • 永远找不到中间被夹住的值

示例 2

swift 复制代码
print(solution.find132pattern([3,1,4,2]))

输出:

text 复制代码
true

解释:

  • 子序列 [1,4,2]
  • 完整满足 132 模式

示例 3

swift 复制代码
print(solution.find132pattern([-1,3,2,0]))

输出:

text 复制代码
true

解释:

  • 存在多组 132
  • 算法只要找到一组就会提前返回

实际场景结合

这道题的思想,在现实中非常常见。

1. 时间序列异常检测

比如股票价格:

  • 先涨
  • 再回落一点
  • 但仍高于早期低点

这本质就是一种 132 模式。

2. 指标反转识别

在监控系统中:

  • 指标低
  • 突然拉高
  • 又回落到中间区间

这类"先拉高再回调"的结构,本质和 132 一样。

3. 为什么栈思路很重要?

因为它能把:

  • "多点关系"
  • "跨区间比较"

压缩成一次线性扫描。

这是工程里非常值钱的能力。

时间复杂度

  • 每个元素最多进栈、出栈一次

时间复杂度:

text 复制代码
O(n)

空间复杂度

  • 使用了一个栈

空间复杂度:

text 复制代码
O(n)

总结

LeetCode 456 是一道非常典型的"思路型"题目

  • 不是靠暴力
  • 不是靠技巧堆叠
  • 而是靠换一个观察角度
相关推荐
dreamxian4 分钟前
苍穹外卖day09
java·spring boot·tomcat·log4j·maven
剑海风云4 分钟前
JDK 26之安全增强
java·开发语言·安全·jdk26
左左右右左右摇晃6 分钟前
Java并发——多线程
java·开发语言·jvm
AMoon丶7 分钟前
Golang--内存管理
开发语言·后端·算法·缓存·golang·os
23.9 分钟前
【Java】字符串底层与常量池演变全解析
java·开发语言·jvm
极客先躯14 分钟前
高级java每日一道面试题-2025年9月09日-数据处理篇[LangChain4j]-金融行业使用 LLM 有哪些合规要求?
java·金融·高级面试题·权限与访问控制·数据脱敏与隐私计算·模型可解释性工具·审计日志与监控
zl_vslam19 分钟前
SLAM中的非线性优-3D图优化之相对位姿Between Factor-四元数(十二)
人工智能·算法·计算机视觉
coding者在努力27 分钟前
算法竞赛中根据数据规模猜测算法
c++·算法·stl·时间复杂度
jing-ya30 分钟前
day 59 图论part10
java·开发语言·数据结构·算法·图论
阿Y加油吧41 分钟前
力扣打卡——搜索二维矩阵、相交链表
线性代数·leetcode·矩阵