Given a sequence of n integers a1, a2, ..., an, a 132 pattern is a subsequence ai, aj, ak such that i < j < k and ai < ak < aj. Design an algorithm that takes a list of n numbers as input and checks whether there is a 132 pattern in the list.

Note: n will be less than 15,000.

Example 1:

Input: [1, 2, 3, 4]

Output: False

Explanation: There is no 132 pattern in the sequence.

Example 2:

Input: [3, 1, 4, 2]

Output: True

Explanation: There is a 132 pattern in the sequence: [1, 4, 2].

Example 3:

Input: [-1, 3, 2, 0]

Output: True

Explanation: There are three 132 patterns in the sequence: [-1, 3, 2], [-1, 3, 0] and [-1, 2, 0].

这道题给我们了一个数组,让我们找到 132 的模式,就是第一个数小于第二第三个数,且第三个数小于第二个数。当然最直接最暴力的方法,就是遍历所有的三个数字的组合,然后验证是否满足这个规律。得莫,OJ 说打妹。那么就只能想办法去优化了,由于暴力搜索的时间复杂度是三次方,在之前的 3Sum 那道题中,我们也有把立方的复杂度减少到平方的复杂度,相当于降了一维(降维打击么?),其实就是先固定一个数字,然后去遍历另外两个数字。我们先确定哪个数字呢,当然是最小的那个啦,我们维护一个变量 mn,初始化为整型最大值,然后在遍历数字的时候,每次用当前数字来更新 mn,然后我们判断,若 mn 为当前数字就跳过,因为需要找到数字j的位置,数字j是大于数字i的,mn 表示的就是数字i。这样数字i和数字j都确定了之后,就要来遍历数字k了,范围是从数组的最后一个位置到数字j之间,只要中间的任何一个数字满足题目要求的关系,就直接返回 true 即可,参见代码如下:

解法一:

class Solution {
public:
bool find132pattern(vector<int>& nums) {
int n = nums.size(), mn = INT_MAX;
for (int j = ; j < n; ++j) {
mn = min(mn, nums[j]);
if (mn == nums[j]) continue;
for (int k = n - ; k > j; --k) {
if (mn < nums[k] && nums[j] > nums[k]) return true;
}
}
return false;
}
};

那么我们就按顺序来找这三个数,首先我们来找第一个数,这个数需要最小,那么我们如果发现当前数字大于等于后面一个数字,我们就往下继续遍历,直到当前数字小于下一个数字停止。然后我们找第二个数字,这个数字需要最大,那么如果我们发现当前数字小于等于下一个数字就继续遍历,直到当前数字大雨下一个数字停止。最后就找第三个数字,我们验证这个数字是否在之前两个数字的中间,如果没有找到,我们就从第二个数字的后面一个位置继续开始重新找这三个数字,参见代码如下:

解法二:
class Solution {
public:
bool find132pattern(vector<int>& nums) {int n = nums.size(), i = , j = , k = ;
while (i < n) {
while (i < n - && nums[i] >= nums[i + ]) ++i;
j = i + ;
while (j < n - && nums[j] <= nums[j + ]) ++j;
k = j + ;
while (k < n) {
if (nums[k] > nums[i] && nums[k] < nums[j]) return true;
++k;
}
i = j + ;
}
return false;
}
};

下面这种方法利用单调栈来做,既简洁又高效,关于单调栈可以参见博主之前的一篇文章 LeetCode Monotonous Stack Summary 单调栈小结。思路是我们维护一个栈和一个变量 third,其中 third 就是第三个数字,也是 pattern 132 中的2,初始化为整型最小值,栈里面按顺序放所有大于 third 的数字,也是 pattern 132 中的3,那么我们在遍历的时候,如果当前数字小于 third,即 pattern 132 中的1找到了,我们直接返回 true 即可,因为已经找到了,注意我们应该从后往前遍历数组。如果当前数字大于栈顶元素,那么我们将栈顶数字取出,赋值给 third,然后将该数字压入栈,这样保证了栈里的元素仍然都是大于 third 的,我们想要的顺序依旧存在,进一步来说,栈里存放的都是可以维持坐标 second > third 的 second 值,其中的任何一个值都是大于当前的 third 值,如果有更大的值进来,那就等于形成了一个更优的 second > third 的这样一个组合,并且这时弹出的 third 值比以前的 third 值更大,为什么要保证 third 值更大,因为这样才可以更容易的满足当前的值 first 比 third 值小这个条件,举个例子来说吧,比如 [2, 4, 2, 3, 5],由于是从后往前遍历,所以后三个数都不会进入 while 循环,那么栈中的数字为 5, 3, 2(其中2为栈顶元素),此时 third 还是整型最小,那么当遍历到4的时候,终于4大于栈顶元素2了,那么 third 赋值为2,且2出栈。此时继续 while 循环,因为4还是大于新栈顶元素3,此时 third 赋值为3,且3出栈。现在栈顶元素是5,那么 while 循环结束,将4压入栈。下一个数字2,小于 third,则找到符合要求的序列 [2, 4, 3],参见代码如下:

解法三:

class Solution {
public:
bool find132pattern(vector<int>& nums) {
int third = INT_MIN;
stack<int> st;
for (int i = nums.size() - ; i >= ; --i) {
if (nums[i] < third) return true;
while (!st.empty() && nums[i] > st.top()) {
third = st.top(); st.pop();
}
st.push(nums[i]);
}
return false;
}
};

讨论:这道题的一个很好的 Follow up 就是求出所有 132 模式的数组,那么解法二和解法三这种想要快速来验证是否存在 132 模式的方法就不太适合,而解法一就比较适合了,我们是需要在找到的时候不直接 return,而是将 mn,数字j,和数字k,放到一个数组里,然后加入结果 res 中,试了题目中的例子3,是可以正确的返回那三个结果的,别的也没怎么试过,感觉应该是正确的。

参考资料:

https://leetcode.com/problems/132-pattern/

https://leetcode.com/problems/132-pattern/discuss/94135/c_ac

https://leetcode.com/problems/132-pattern/discuss/94133/Simple-java-accepted-well-explained-O(n2)-solution

https://leetcode.com/problems/132-pattern/discuss/94071/single-pass-c-on-space-and-time-solution-8-lines-with-detailed-explanation

https://leetcode.com/problems/132-pattern/discuss/94089/Java-solutions-from-O(n3)-to-O(n)-for-%22132%22-pattern-(updated-with-one-pass-slution)

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 132 Pattern 132模式的更多相关文章

  1. 456 132 Pattern 132模式

    给定一个整数序列:a1, a2, ..., an,一个132模式的子序列 ai, aj, ak 被定义为:当 i < j < k 时,ai < ak < aj.设计一个算法,当 ...

  2. [LeetCode] Word Pattern 词语模式

    Given a pattern and a string str, find if str follows the same pattern. Examples: pattern = "ab ...

  3. 456. 132 Pattern

    456. 132 Pattern Given an array of integers a1, a2, a3-an, judge if there exists the 132 pattern. 13 ...

  4. [Swift]LeetCode456. 132模式 | 132 Pattern

    Given a sequence of n integers a1, a2, ..., an, a 132 pattern is a subsequence ai, aj, ak such that  ...

  5. 【LeetCode】456. 132 Pattern 解题报告(Python)

    [LeetCode]456. 132 Pattern 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fu ...

  6. Leetcode: 132 Pattern

    Given a sequence of n integers a1, a2, ..., an, a 132 pattern is a subsequence ai, aj, ak such that ...

  7. 【LeetCode】456. 132 Pattern

    Given a sequence of n integers a1, a2, ..., an, a 132 pattern is a subsequence ai, aj, ak such that  ...

  8. LeetCode解题报告—— 1-bit and 2-bit Characters & 132 Pattern & 3Sum

    1. 1-bit and 2-bit Characters We have two special characters. The first character can be represented ...

  9. [leetcode] 456. 132 Pattern (Medium)

    对一个三个元素以上的数组,如果存在1-3-2模式的组合,则返回true. 1-3-2模式就是值的排序是i<k<j但是下标排序是i<j<k. 解法一: 硬解,利用一个变量存储是否 ...

随机推荐

  1. Vertica集群单节点宕机恢复方法

    Vertica集群单节点宕机恢复方法 第一种方法: 直接通过admintools -> 5 Restart Vertica on Host 第二种方法: 若第一种方法无法恢复,则清空宕机节点的c ...

  2. 自己动手,实现一种类似List<T>的数据结构(二)

    前言: 首先,小匹夫要祝各位看官圣诞快乐,新年愉快-.上一篇文章<自己动手,实现一种类似List<T>的数据结构(一)> 介绍了一下不依靠List<T>实现的各种接 ...

  3. FFmpeg学习1:视频解码

    在视频解码前,先了解以下几个基本的概念: 编解码器(CODEC):能够进行视频和音频压缩(CO)与解压缩(DEC),是视频编解码的核心部分. 容器/多媒体文件(Container/File):没有了解 ...

  4. Java DNS查询内部实现

    源码分析 在Java中,DNS相关的操作都是通过通过InetAddress提供的API实现的.比如查询域名对应的IP地址: String dottedQuadIpAddress = InetAddre ...

  5. Basic Tutorials of Redis(7) -Publish and Subscribe

    This post is mainly about the publishment and subscription in Redis.I think you may subscribe some o ...

  6. asp.net记录错误日志的方法

    1.说明 在调试发布后的asp.net项目时有可能会遇到意想不到的错误,而未能及时的显示.这就需要记录日志来跟踪错误信息,所以写了个简单的记录信息的方法,记录简单的文本信息也可以使用.此方法是以生成文 ...

  7. C#开发微信门户及应用(22)-微信小店的开发和使用

    在做企业电子商务方面,微信小店虽然较淘宝天猫等起步较晚,但是作为一个电商平台,这个影响力不容忽视,结合微信的特点和便利,微信小店具有很好的粘合性和广泛的用户基础,因此花费一定的时间,在这方面做深入的研 ...

  8. PHP 代理模式

    代理模式:为其他对象提供一种代理以控制对这个对象的访问. [代理模式中主要角色] 抽象主题角色:声明了代理主题和真实主题的公共接口,使任何需要真实主题的地方都能用代理主题代替. 代理主题角色:含有真实 ...

  9. 关于IOS中safari下的select下拉菜单,文字过长不换行的问题

    今天遇到下图这种问题,文字过长,显示不全.折腾了老半天,在网上搜了半天也找不到解决方案. 于是问了下同事,同事提到了<optgroup>,这个标签厉害. <optgroup> ...

  10. 深入理解DOM节点类型第六篇——特性节点Attribute

    × 目录 [1]特征 [2]属性 [3]方法 前面的话 元素的特性在DOM中以Attr类型表示,从技术角度讲,特性是存在于元素的attributes属性中的节点.尽管特性是节点,但却不是DOM节点树的 ...