@author: sdubrz
@date: 2020.0412
題目難度: 中等
考察內容: 棧
原題鏈接 https://leetcode-cn.com/problems/132-pattern/
題目的著作權歸領釦網絡所有,商業轉載請聯繫官方授權,非商業轉載請註明出處。
解題代碼轉載請聯繫 lwyz521604#163.com
給定一個整數序列:a1, a2, …, an,一個132模式的子序列 ai, aj, ak 被定義爲:當 i < j < k 時,ai < ak < aj。設計一個算法,當給定有 n 個數字的序列時,驗證這個序列中是否含有132模式的子序列。
**注意:**n 的值小於15000。
示例1:
輸入: [1, 2, 3, 4]
輸出: False
解釋: 序列中不存在132模式的子序列。
示例 2:
輸入: [3, 1, 4, 2]
輸出: True
解釋: 序列中有 1 個132模式的子序列: [1, 4, 2].
示例 3:
輸入: [-1, 3, 2, 0]
輸出: True
解釋: 序列中有 3 個132模式的的子序列: [-1, 3, 2], [-1, 3, 0] 和 [-1, 2, 0].
通過次數 7431
提交次數 28142
常規方法
這道題官方給的標籤是棧,但是我沒有想出用棧的實現方式。最後寫了一個用 ArrayList 實現的版本,提交之後通過了,但是排名比較低。主要的思路就是對於一個數對(a, b),其中 a<b ,判斷它們後面的數 c 是否滿足 a<c<b 。從左到右掃描一遍數組,用兩個 ArrayList 分別存儲 a 和 b。時間複雜度應該是的吧。
Java實現如下:
class Solution {
public boolean find132pattern(int[] nums) {
if(nums.length<3) {
return false;
}
ArrayList<Integer> maxs = new ArrayList<>();
ArrayList<Integer> mins = new ArrayList<>();
int minIndex0 = 0;
int maxIndex0 = 0;
int itex = 1;
while(itex<nums.length && minIndex0>=maxIndex0) {
if(nums[itex]<nums[minIndex0]) {
minIndex0 = itex;
maxIndex0 = itex;
}else if(nums[itex]>nums[maxIndex0]) {
maxIndex0 = itex;
}
itex++;
}
if(minIndex0>=maxIndex0) {
return false;
}
maxs.add(nums[maxIndex0]);
mins.add(nums[minIndex0]);
while(itex<nums.length) {
// System.out.println("current number: "+nums[itex]);
int n = maxs.size();
for(int i=n-1; i>=0; i--) {
if(nums[itex]>mins.get(i) && nums[itex]<maxs.get(i)) {
return true;
}
}
if(maxs.size()==mins.size()) { // 一樣長
if(nums[itex]>maxs.get(n-1)) {
maxs.set(n-1, nums[itex]);
}else if(nums[itex]<mins.get(n-1)){
mins.add(nums[itex]);
}
}else{ // 最大鏈表不可能比小鏈表長
if(nums[itex]>mins.get(mins.size()-1)) {
maxs.add(nums[itex]);
}
}
itex++;
}
return false;
}
}
在 LeetCode 系統中提交的結果如下
執行結果: 通過 顯示詳情
執行用時 : 266 ms, 在所有 Java 提交中擊敗了 22.65% 的用戶
內存消耗 : 40.4 MB, 在所有 Java 提交中擊敗了 35.29% 的用戶
棧方法
下面是官方給出的棧的實現方法
這個方法的時間複雜度降到了 。官方代碼如下
public class Solution {
public boolean find132pattern(int[] nums) {
if (nums.length < 3)
return false;
Stack < Integer > stack = new Stack < > ();
int[] min = new int[nums.length];
min[0] = nums[0];
for (int i = 1; i < nums.length; i++)
min[i] = Math.min(min[i - 1], nums[i]);
for (int j = nums.length - 1; j >= 0; j--) {
if (nums[j] > min[j]) {
while (!stack.isEmpty() && stack.peek() <= min[j])
stack.pop();
if (!stack.isEmpty() && stack.peek() < nums[j])
return true;
stack.push(nums[j]);
}
}
return false;
}
}