算法初探LeetCode-数组中的最长山脉

224 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 29 天,点击查看活动详情

LeetCode845:数组中的最长山脉

把符合下列属性的数组 arr 称为 山脉数组 :

  • arr.length >= 3

  • 存在下标 i0 < i < arr.length - 1),满足

    • arr[0] < arr[1] < ... < arr[i - 1] < arr[i]
    • arr[i] > arr[i + 1] > ... > arr[arr.length - 1]

给出一个整数数组 arr,返回最长山脉子数组的长度。如果不存在山脉子数组,返回 0 。

示例 1:

输入: arr = [2,1,4,7,3,2,5]
输出: 5
解释: 最长的山脉子数组是 [1,4,7,3,2],长度为 5。

示例 2:

输入: arr = [2,2,2]
输出: 0
解释: 不存在山脉子数组。

提示:

  • 1<=arr.length<=1041 <= arr.length <= 10^4
  • 0<=arr[i]<=1040 <= arr[i] <= 10^4

思路分析

由本题意可知:

山峰是先递增然后递减,递减反过来看也是递增,从左到右计算最长递增子数组的个数,从右到左计算最长递增子数组的个数。

枚举山顶的实现,用dp1[i]记录第i个节点左侧上升山脉长度,于是dp[i] = dp[i-1] + 1;同样的逻辑进行倒叙遍历,那么所得就是第i个节点右侧上升山脉的长度。

  • 1.经过分析可得,我们可以在遍历一次列表之后即可得出题解
  • 2.从左往右遍历,当前数比下一个数小的,我们记为ans+1,不过这里有一个判断条件:如果之前右山峰不为零,即tem!=0,那我们需要重置这个左山峰
  • 3.当前数大于下一个数,并且左山峰不为零,那我们就可以使右山峰加一

算法代码

public int longestMountain(int[] A) {
    int len = A.length;
    int left = 0;
    int right = 0;
    int max = 0;
    for (int i = 0; i < len - 1; i++) {
        if (A[i] < A[i + 1]) { //表示左山峰
            if (right != 0) { //表示上一次是右山峰
                left = 0;
                right = 0;
            }
            left++;
        } else if (left != 0 && A[i] > A[i + 1]) { //右山峰
            right++;
            max = Math.max(max, left + right + 1);
        } else if (A[i] == A[i + 1]) {
            left = 0;
        }
    }
    return max;
}

结果详情

Snipaste_2023-03-04_22-31-14.png

算法复杂度

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!