123模式
Posted Myuniverse
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了123模式相关的知识,希望对你有一定的参考价值。
超级暴力解法
思路:循环三次
func find132pattern1(nums []int) bool {
if len(nums)<=2{
return false
}
for i:=0;i<len(nums);i++{
for j:=i+1;j<len(nums);j++{
for k:=j+1;k<len(nums);k++{
if nums[i] < nums[k] && nums[k] < nums[j]{
return true
}
}
}
}
return false
}
结果:超时
优化解法
上面的做法是分别对三个数进行枚举,这样做法是O(n3)的,数据范围是104,稳稳的超时。
因此,我们可以从132的大小特性去分析,如果在确定一个数之后,如何快速找到另外两个数(我们使用ijk来指代132结构):
- 枚举i:由于i是132结构中最小的数,那么相当于我们要从i后面,找到一个对数(j,k),是的(j,k)都满足比i大,同时j和k之间存在j>k的关系。由于我们遍历是单向的,因此我们可以将问题转化为找k,首先k需要比i大,同时在[i,k]之间存在比k大的数
- 枚举 j:由于 j 是 132 结构里最大的数,因此我们需要在 j 的右边中比 j 小的「最大」的数,在 j 的左边找比 j 小的「最小」的数。这很容易联想到单调栈,但是朴素的单调栈是帮助我们找到左边或者右边「最近」的数,无法直接满足我们「最大」和「最小」的要求,需要引入额外逻辑。
- 枚举 k:由于 k 是 132 结构中的中间值,这里的分析逻辑和「枚举 i」类似,因为遍历是单向的,我们需要找到 k 左边的 i,同时确保 [i,k] 之间存在比 i 和 k 大的数字。
以上三种分析方法都是可行的,这里只做枚举i的做法。
过程:我们从后往前做,维护一个「单调递减」的栈,同时使用 k 记录所有出栈元素的最大值(k 代表满足 132 结构中的 2)。
那么当我们遍历到 i,只要满足发现满足 nums[i] < k,说明我们找到了符合条件的 i j k。
举个
以上是关于123模式的主要内容,如果未能解决你的问题,请参考以下文章
[Go] 通过 17 个简短代码片段,切底弄懂 channel 基础