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

博客园:https://www.cnblogs.com/PythonFCG/p/13872391.html
原题地址: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。

动态规化

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

  • 如果 A [ i ] > A [ i − 1 ] A[i] > A[i-1] A[i]>A[i1] 那么 l e f t [ i ] = l e f t [ i − 1 ] + 1 left[i]=left[i-1]+1 left[i]=left[i1]+1;如果 i = 0 则 l e f t [ i ] = 0 i=0则left[i]=0 i=0left[i]=0

  • 如果 A [ i ] > A [ i + 1 ] A[i] > A[i+1] A[i]>A[i+1] 那么 r i g h t [ i ] = r i g h t [ i + 1 ] + 1 right[i]=right[i+1]+1 right[i]=right[i+1]+1;如果 i = n − 1 则 r i g h t [ i ] = 0 i=n-1则right[i]=0 i=n1right[i]=0

计算出所有的 l e f t [ ] , r i g h t [ ] left[],right[] left[],right[]后就可以枚举山顶,但是需要注意只有当 l e f t [ i ] > 0 并 且 r i g h t [ i ] > 0 left[i] > 0 并且 right[i] >0 left[i]>0right[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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>