[leetCode]845. 数组中的最长山脉

csdn:https://blog.csdn.net/renweiyi1487/article/details/109270033
原题地址:https://leetcode-cn.com/problems/longest-mountain-in-array

我们把数组 A 中符合下列属性的任意连续子数组 B 称为 “山脉”:

B.length >= 3
存在 0 < i < B.length - 1 使得 B[0] < B[1] < ... B[i-1] < B[i] > B[i+1] > ... > B[B.length - 1]
(注意:B 可以是 A 的任意子数组,包括整个数组 A。)

给出一个整数数组 A,返回最长 “山脉” 的长度。

如果不含有 “山脉” 则返回 0。

动态规化

 由于从左侧山脚到山顶,与从右侧山脚到山顶是严格单调递增的所以可以使用动态规化。
 另$left[i]$表示$A[i]$左侧可以扩展的数量,$right[i]$表示$A[i]$右侧可以扩展的数量,

  • 如果$A[i] > A[i-1]$ 那么$left[i]=left[i-1]+1$;如果$i=0则left[i]=0$

  • 如果$A[i] > A[i+1]$ 那么$right[i]=right[i+1]+1$;如果$i=n-1则right[i]=0$

计算出所有的$left[],right[]$后就可以枚举山顶,但是需要注意只有当$left[i] > 0 并且 right[i] >0$时A[i]才是山顶。

class Solution {
    public int longestMountain(int[] A) {
        int n = A.length;
        if (n == 0) {
            return 0;
        }
        // left[i] 表示A[i]左侧最多能扩展的数目
        int[] left = new int[n];
        for (int i = 1; i < n; i++) {
            left[i] = A[i] > A[i-1] ? left[i-1]+1 : 0;
        }
        // right[i] 表示A[i]右侧最多能扩展的数目
        int[] right = new int[n];
        for (int i = n-2; i >=0; i--) {
            right[i] = A[i] > A[i+1] ? right[i+1] + 1 : 0;
        }
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (left[i] > 0 && right[i] >0) {
                ans = Math.max(ans, left[i] + right[i] + 1);
            }
        }
        return ans;
    }
}

双指针

定义一个左指针初始值为0指向山脚,每次固定left时需要保证:

  • left + 2 < n 因为山脉的长度至少为三
  • 然后设置right 指针为left+1,如果left在山脚则控制right指针爬山
  • 如果right指针爬到的是山顶则控制right指针下山,然后计算山脉长度,如果right指针爬到的不是山顶则让right指针+1,每寻找一次山脚就要重新固定left
class Solution {
    public int longestMountain(int[] A) {
        int n = A.length;
        if (n == 0) {
            return 0;
        }
        int left = 0, ans = 0;
        while (left + 2 < n) {
            int right = left + 1;
            if (A[left] < A[left+1]) {
                while (right + 1 < n && A[right] < A[right+1]) {
                    right++;
                }
                if (right + 1 < n && A[right] > A[right+1]) {
                    while (right + 1 < n && A[right] > A[right+1]) {
                        right++;
                    }
                    ans = Math.max(ans, right-left+1);
                } else {
                    right++;
                }
            }
            left = right;
        }
        return ans;
    }
}
posted @ 2020-10-25 10:15  消灭猕猴桃  阅读(108)  评论(0编辑  收藏  举报