[LeetCode] 132 Pattern 132模式
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
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 132 Pattern 132模式的更多相关文章
- 456 132 Pattern 132模式
给定一个整数序列:a1, a2, ..., an,一个132模式的子序列 ai, aj, ak 被定义为:当 i < j < k 时,ai < ak < aj.设计一个算法,当 ...
- [LeetCode] Word Pattern 词语模式
Given a pattern and a string str, find if str follows the same pattern. Examples: pattern = "ab ...
- 456. 132 Pattern
456. 132 Pattern Given an array of integers a1, a2, a3-an, judge if there exists the 132 pattern. 13 ...
- [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 ...
- 【LeetCode】456. 132 Pattern 解题报告(Python)
[LeetCode]456. 132 Pattern 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fu ...
- Leetcode: 132 Pattern
Given a sequence of n integers a1, a2, ..., an, a 132 pattern is a subsequence ai, aj, ak such that ...
- 【LeetCode】456. 132 Pattern
Given a sequence of n integers a1, a2, ..., an, a 132 pattern is a subsequence ai, aj, ak such that ...
- 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 ...
- [leetcode] 456. 132 Pattern (Medium)
对一个三个元素以上的数组,如果存在1-3-2模式的组合,则返回true. 1-3-2模式就是值的排序是i<k<j但是下标排序是i<j<k. 解法一: 硬解,利用一个变量存储是否 ...
随机推荐
- nginx简易教程
概述 什么是nginx? Nginx (engine x) 是一款轻量级的Web 服务器 .反向代理服务器及电子邮件(IMAP/POP3)代理服务器. 什么是反向代理? 反向代理(Reverse Pr ...
- 代码的坏味道(8)——被拒绝的馈赠(Refused Bequest)
坏味道--被拒绝的馈赠(Refused Bequest) 特征 子类仅仅使用父类中的部分方法和属性.其他来自父类的馈赠成为了累赘. 问题原因 有些人仅仅是想重用超类中的部分代码而创建了子类.但实际上超 ...
- git 版本回退
由于操作失误,需要将代码进行版本回退,首先在本地仓库执行了“git reset --hard HEAD^”命令,这样只会回退本地仓库的代码,但是我的代码之前已经push到了远程库中,查看远程仓库,发现 ...
- C#——字段和属性
//我的C#是跟着猛哥(刘铁猛)(算是我的正式老师)<C#语言入门详解>学习的,微信上猛哥也给我讲解了一些不懂得地方,对于我来说简直是一笔巨额财富,难得良师! 在刚开始学习属性这一节时,开 ...
- spring/spring boot/spring cloud开发总结
背景 针对RPC远程调用,都在使用dubbo.dubbox等,我们也是如此.由于社区暂停维护.应对未来发展,我们准备尝试新技术(或许这时候也不算什么新技术了吧),选择使用了spring ...
- Lightbox改造——支持滚轮缩放
在做文章类型的web页时,经常会遇到要点开看大图的需求,LightBox2则是在众多产品中比较优秀的一款Jquery插件.配置就不细说了,今天我主要要分享的是:如何在点开大图后,可以通过鼠标滚轮来缩放 ...
- 【干货分享】前端面试知识点锦集04(Others篇)——附答案
四.Others部分 技术类 1.http状态码有哪些?分别代表是什么意思? (1).成功2×× 成功处理了请求的状态码.200 服务器已成功处理了请求并提供了请求的网页.204 服务器成功处理了请求 ...
- Dynamics CRM 之ADFS 使用 WID 和代理的联合服务器场
为此部署拓扑 Active Directory 联合身份验证服务 (AD FS) 等同于联合服务器场与 Windows 内部数据库 (WID) 拓扑中,但它将代理服务器计算机添加到外围网络,以支持外部 ...
- 原创炫酷代码公开——连接董铂然github
公开了github部分项目(均为原创)更多代码请看https://github.com/dsxNiubility SXWaveAnimate Wonderful SXPhotoShow SXNews ...
- Oracle连接odbc数据源
Oracle连接odbc数据源 说明 oracle连接ODBC数据源有两种方式,hsodbc和dg4odbc,简单说dg4odbc是hsodbc的升级.两种连接方法大致一样,现将连接步骤说明如下: 检 ...