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。

举个🌰,对于样例数据 [3, 1, 4, 2],我们知道满足 132 结构的子序列是 [1, 4, 2],其处理逻辑是(遍历从后往前):

枚举到 2:栈内元素为 [2],k = INF
枚举到 4:不满足「单调递减」,2 出栈更新 k,4 入栈。栈内元素为 [4],k = 2
枚举到 1:满足 nums[i] < k,说明对于 i 而言,后面有一个比其大的元素(满足 i < k 的条件),同时这个 k 的来源又是因为维护「单调递减」而弹出导致被更新的(满足 i 和 k 之间,有比 k 要大的元素)。因此我们找到了满足 132 结构的组合。
这样做的本质是:我们通过维护「单调递减」来确保已经找到了有效的 (j,k)。换句话说如果 k 有值的话,那么必然是因为有 j > k,导致的有值。也就是 132 结构中,我们找到了 32,剩下的 i (也就是 132 结构中的 1)则是通过遍历过程中与 k 的比较来找到。这样做的复杂度是 O(n)O(n) 的,比树状数组还要快。

// 固定j找i和k
func find132pattern(nums []int)bool{
	if len(nums)<3{
		return false
	}
	n := len(nums)
	candidateK := []int{nums[n-1]}   // 这里用来存储满足,小于nums[j]的nums[k]
	maxK := math.MinInt64     // 所有满足nums[j]>nums[k]的nums[k]的最大值

	// 固定j
	for i:=n-2;i>=0;i--{
		// 这里已经知道k了,查找j和i
		if nums[i] <maxK {
			return true
		}

		// 这里找出满足nums[i]>nums[k]的所有nums[k]的值,并且求出所有满足nums[k]<nums[i]的nums[k]的最大值
		for len(candidateK)>0 && nums[i] > candidateK[len(candidateK)-1] {
			maxK = candidateK[len(candidateK)-1]
			candidateK = candidateK[:len(candidateK)-1]    // 这里将满足的值去掉
		}
		// 若nums[i]大于maxk,则将nums[i]的值也加进去单调栈中
		if nums[i] > maxK{
			candidateK = append(candidateK,nums[i])
		}
	}

	return false
}

过程图片:456.gif

参考文献:

宫水三叶の相信科学系列:https://leetcode-cn.com/problems/132-pattern/solution/xiang-xin-ke-xue-xi-lie-xiang-jie-wei-he-95gt/

posted @ 2021-05-29 21:47  Myuniverse  阅读(71)  评论(0编辑  收藏  举报