1. 程式人生 > 實用技巧 >845. [陣列][雙指標]陣列中的最長山脈

845. [陣列][雙指標]陣列中的最長山脈

845. 陣列中的最長山脈

重陽節登高⛰️?

方法一:列舉

上山部分和下山部分分別是嚴格單調遞增嚴格單調遞減的。if (!upSide)不成立時,對應的是”平坡“,左山腳指標將前移。

// 執行耗時:3 ms,擊敗了69.39% 的Java使用者
// 記憶體消耗:39.5 MB,擊敗了86.02% 的Java使用者

class Solution {
    public int longestMountain(int[] A) {
        if (A == null || A.length < 3) {  // 如果陣列長度不足3,直接返回0
            return 0;
        }

        int curLength = 1;
        int maxLength = 0;
        boolean upSide = true;  // 標識位,true表示當前處於上坡,false則表示處於下坡
        for (int i = 1; i < A.length; i++){
            if (A[i] > A[i - 1] && upSide) {
                curLength++;
            } else if (A[i] < A[i - 1] && curLength > 1) {
                upSide = false;
                curLength++;
                maxLength = Math.max(curLength, maxLength);
            } else {
                if (!upSide){
                    i--;  // 判斷下一個山脈時,指標前移,而後的當前指標才為第一個需要判斷的元素
                }
                upSide = true;
                curLength = 1;
            }
        }
        return maxLength;
    }
}

方法二:雙指標

同向雙指標的做法類似於直接列舉模擬,要額外注意防止越界。

// 執行耗時:2 ms,擊敗了99.84% 的Java使用者
// 記憶體消耗:39.4 MB,擊敗了90.44% 的Java使用者

class Solution {
    public int longestMountain(int[] A) {
        if (A == null || A.length < 3) {
            return 0;
        }
        int maxLength = 0;
        int l1 = 0, l2 = 0;
        while (l2 < A.length) {
            while (l2 + 1 < A.length && A[l2 + 1] > A[l2]) {  // 防止越界,判斷是否在上山
                l2++;
            }
            int tmp = l2;  // 用於之後判斷是否經歷下山
            while (l2 > l1 && l2 + 1 < A.length && A[l2+1] < A[l2]) {  // 防止越界,判斷是否在下山
                l2++;
            }
            if (l2 == tmp){  // l2沒有下山(例如已經到了A的末尾或是處於平坡)
                l2++;        // 此時不符合要求,指標後移
                l1 = l2;
            } else {  // 儲存一次山脈長度,更新左指標
                maxLength = Math.max(maxLength, l2 - l1 + 1);
                l1 = l2;
            }
        }
        return maxLength;
    }
}