算法随笔_19: 数组中的最长山脉

发布于:2025-02-10 ⋅ 阅读:(42) ⋅ 点赞:(0)

上一篇:算法随笔_18: 划分字母区间-CSDN博客

======================

题目描述如下:

把符合下列属性的数组 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。

======================

算法思路:

根据题目要求,山脉数组的样式需要以一个元素为山顶,向两边数值递减。那么这个元素左侧递减延伸的长度加上右侧递减延伸的长度,即为以这个元素为山顶的山脉的长度。

我们枚举数组中的所有元素,对于每个元素,我们都计算一下以这个元素为山顶的山脉长度。最后取一个最大值即为答案。

那么如何计算这个元素左侧递减延伸的长度呢?通过分析,我们又发现了另一个现象。我们设元素i的左侧递减延伸的长度为eL,如果元素i的数值小于元素i+1的数值,那么元素i+1的左侧递减延伸的长度就为eL+1。

很明显,这是一个递推的情形。我们可以从左向右遍历数组。计算出所有元素的左侧递减延伸的长度,并记录在变量expandL中。

同理,我们设元素i的右侧递减延伸的长度为eR,如果元素i的数值小于元素i-1的数值,那么元素i-1的右侧递减延伸的长度就为eR+1。我们可以从右向左遍历数组。计算出所有元素的右侧递减延伸的长度,并记录在变量expandR中。

最终,每个元素为山顶的山脉长度就等于eL+eR+1。

下面是代码实现:

注: 代码中的expandR数组的顺序与arr的顺序正好相反,即,expandR数组的第1个元素表示以arr数组最后一个元素为山顶的右侧递减延伸的长度。以此类推。

class Solution(object):
    def longestMountain(self, arr):
        """
        :type arr: List[int]
        :rtype: int
        """
        expandL=[0]
        expandR=[0]
        arrLen=len(arr)
        for i in range(1,arrLen):
            if arr[i]>arr[i-1]:
                expandL.append(expandL[i-1]+1)
            else:
                expandL.append(0)

            if arr[arrLen-i]<arr[arrLen-i-1]:
                expandR.append(expandR[i-1]+1)
            else:
                expandR.append(0)
        maxL=0       
        for i in range(arrLen):
            eL=expandL[i]
            eR=expandR[arrLen-i-1]
            if eL==0 or eR==0:
                continue
            mLen=eL+eR+1
            maxL=max(maxL,mLen)
             
        return maxL