1. 程式人生 > >[Leetcode456] 132模式 峰谷法/單調棧

[Leetcode456] 132模式 峰谷法/單調棧

一個 lean lock http 匹配 i++ 空間 模式 erl

題目:https://leetcode-cn.com/problems/132-pattern/

思路:

  如果某個數左邊比它小的數的最小值,小於它右邊小於它的某個數(不必找最大值),那麽這個序列就符合132模式的定義。如下圖三點所示。

技術分享圖片

  於是有解法1(峰谷法):

 1 public static boolean find132pattern(int[] nums) {
 2     int min = Integer.MAX_VALUE;
 3     int max = Integer.MIN_VALUE;
 4     boolean one = false;
 5
boolean three = false; 6 for (int i = 0; i < nums.length; i++) { 7 // 8 if (!one && i < nums.length - 1 && nums[i + 1] > nums[i]) { 9 one = true; 10 three = false; 11 min = nums[i]; 12 continue
; 13 } 14 // 15 if (one && i < nums.length - 1 && nums[i + 1] < nums[i]) { 16 three = true; 17 one = false; 18 max = nums[i]; 19 for (int j = i + 1; j < nums.length; j++) { 20 if (nums[j] < max && nums[j] > min) {
21 return true; 22 } 23 } 24 continue; 25 } 26 } 27 return false; 28 }

  解法1的基本思路就是先找到一對“1”和“3”,然後掃描“3”的右方,找到“2”。

  提交結果是219 ms擊敗39.66、47.3 MB擊敗0%。

  解法2(單調棧):

 1 public static boolean find132pattern(int[] nums) {
 2     if (nums.length == 0) {
 3         return false;
 4     }
 5     // 記錄每一個數左邊的最小值 空間換時間
 6     int[] leftMins = new int[nums.length];
 7     // 記錄目前出現的最小值
 8     int leftMin = Integer.MAX_VALUE;
 9     for (int i = 0; i < nums.length; i++) {
10         leftMins[i] = leftMin;
11         if (nums[i] < leftMin) {
12             leftMin = nums[i];
13         }
14     }
15     // 從右開始掃描的非遞增棧 存下標
16     Deque<Integer> stack = new LinkedList<>();
17     for (int i = nums.length - 1; i > 0; i--) {
18         while (!stack.isEmpty() && nums[stack.peekLast()] < nums[i]) {
19             if (nums[stack.pollLast()] > leftMins[i]) {
20                 return true;
21             }
22         }
23         stack.offerLast(i);
24     }
25     return false;
26 }

  首先從左往右掃描一遍,記錄每個數作為“3”時對應的最小的“1”。然後從右往左掃描,維持一個非遞增棧,把小於或等於棧頂的值壓入棧中,棧中的所有數都是備選的“2”。一旦發現有大於棧頂的數,就以這個數為“3”,用它對應的最小的“1”和棧中備選的“2”比較,一旦有符合“1”<“2”的情況,就匹配成功。

  提交結果是19 ms擊敗94.33%,48.3 MB擊敗0%。

[Leetcode456] 132模式 峰谷法/單調棧