1. 程式人生 > 實用技巧 >[LeetCode] 845. Longest Mountain in Array

[LeetCode] 845. Longest Mountain in Array

Let's call any (contiguous) subarray B (of A)amountainif the following properties hold:

  • B.length >= 3
  • There exists some0 < i< B.length - 1such thatB[0] < B[1] < ... B[i-1] < B[i] > B[i+1] > ... > B[B.length - 1]

(Note that B could be any subarray of A, including the entire array A.)

Given an arrayAof integers,return the length of the longestmountain.

Return0if there is no mountain.

Example 1:

Input: [2,1,4,7,3,2,5]
Output: 5
Explanation: The largest mountain is [1,4,7,3,2] which has length 5.

Example 2:

Input: [2,2,2]
Output: 0
Explanation: There is no mountain.

Note:

  1. 0 <= A.length <= 10000
  2. 0 <= A[i] <= 10000

Follow up:

  • Can you solve it using only one pass?
  • Can you solve it inO(1)space?

陣列中的最長山脈。題意是給一個數組,請你返回一個最長的山脈陣列。山脈陣列的定義是

  • B.length >= 3
  • 存在 0 < i< B.length - 1 使得 B[0] < B[1] < ... B[i-1] < B[i] > B[i+1] > ... > B[B.length - 1]

這道題不涉及演算法,思路是雙指標。我先給一個需要額外空間的做法。建立兩個額外陣列,與input陣列等長,一個叫做up,一個叫做down,目的是記錄陣列中間單調遞增和單調遞減的部分到底有多長。首先把陣列從右往左掃描,判斷nums[i] > nums[i + 1]。如果滿足這個條件,就down[i] = down[i + 1] + 1,記錄一個區域性的遞減子陣列的長度。一旦不滿足這個條件的話,down[i] = 0。

再次掃描陣列,這一次從左往右掃描,如果nums[i] > nums[i - 1],則up[i] = up[i - 1] + 1,這是在記錄一個區域性的遞增子陣列的長度。同時我們可以計算最大子陣列的長度了,如果up[i] > 0 && down[i] > 0, res = up[i] + down[i] + 1。

時間O(n)

空間O(n)

Java實現

 1 class Solution {
 2     public int longestMountain(int[] A) {
 3         int len = A.length;
 4         int res = 0;
 5         int[] up = new int[len];
 6         int[] down = new int[len];
 7         for (int i = len - 2; i >= 0; i--) {
 8             if (A[i] > A[i + 1]) {
 9                 down[i] = down[i + 1] + 1;
10             }
11         }
12 
13         for (int i = 0; i < len; i++) {
14             if (i > 0 && A[i] > A[i - 1]) {
15                 up[i] = up[i - 1] + 1;
16             }
17             if (up[i] > 0 && down[i] > 0) {
18                 res = Math.max(res, up[i] + down[i] + 1);
19             }
20         }
21         return res;
22     }
23 }

另外我這裡再提供一種不需要額外空間的做法,只掃描一次。從左往右掃描陣列,如果nums[i] > nums[i - 1],那麼這一段就是上升的,用一個變數記錄最大的上升長度up;這裡我們是用一個while迴圈控制,所以一旦跳出這個while迴圈你就知道可能要開始下降了(也有可能是平的,這裡要注意)。所以這時我們再用一個變數down記錄下降部分的長度,也用while迴圈控制,當不滿足while的條件的時候,down也停止記錄了。此時如果up和down都大於0,就更新res。

時間O(n)

空間O(1)

Java實現

 1 class Solution {
 2     public int longestMountain(int[] A) {
 3         int maxMnt = 0;
 4         int i = 1;
 5         while (i < A.length) {
 6             while (i < A.length && A[i - 1] == A[i]) {
 7                 i++;
 8             }
 9 
10             int up = 0;
11             while (i < A.length && A[i - 1] < A[i]) {
12                 ++up;
13                 ++i;
14             }
15 
16             int down = 0;
17             while (i < A.length && A[i - 1] > A[i]) {
18                 ++down;
19                 ++i;
20             }
21 
22             if (up > 0 && down > 0) {
23                 maxMnt = Math.max(maxMnt, up + down + 1);
24             }
25         }
26         return maxMnt;
27     }
28 }

LeetCode 題目總結