【5分钟力扣】845. 数组中的最长山脉

一、前言

人只能活一回,梦想却有无数个,唯有放手一搏,才能知道机会属不属于自己。

每天五分钟,看懂一道简单、中等难度的算法题,尽可能将复杂的题讲清楚。

疯狂学习python中,2020-10-25更新

二、题目

我们把数组 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。

示例 1:

输入:[2,1,4,7,3,2,5]
输出:5
解释:最长的 “山脉” 是 [1,4,7,3,2],长度为 5。

示例 2:

输入:[2,2,2]
输出:0
解释:不含 “山脉”。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-mountain-in-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

三、解法和思路

1、思考步骤

  1. 对于一个数组组成的山脉, 一定满足 B[i-1] < B[i] > B[B.length - 1] B[i]是山顶最高值,B[i-1]则是一个单调递增的区间, B[B.length-1]是一个单调递减的区间
  2. 我们从列表A首元素开始找,当找到前i个元素都是递增时,且i的长度 >=2 ,说明找到了左侧山脉
  3. 我们从列表A逆序查找,当找到i个元素都是递增时,且i的长度>=2 ,说明找到右侧山峰
  4. 通过遍历数组A,如果左侧山脉与右侧山脉基于某一点重合,则说明找到了一条山脉。

可以设置一个值记录山脉长度,然后将多个山脉进行长度比较,返回最长的那个值。

1、思考左侧边界问题
我们用left[i]来表示左侧最多能拓展的元素个数
  如果 A[i−1] < A[i] ,意味着能拓展向左拓展更多一位元素,那么有公式
      left[i] = left[i-1] +1
  如果 A[i-1] > A[i]
       left[i] = 0
 当 i=0 时,A[i] 为首元素,无法向左扩展,因此同样有
       left[0] = 0

2、 思考右侧边界问题
我们用right[i]来表示左侧最多能拓展的元素个数
  如果A[i+1] < A[i],意味着能向右拓展一个元素,那么由公式
      right[i] = right[i+1] +1
  如果A[i+1] > A[i]
      right[i] = 0

3、 思考山脉合并问题
当我们得到所有的left[]以及right[]的时候,就可以通过遍历列举出山顶了
只有当left[i]和left[i]均大于0的时候,A[i]才能作为山顶


四、代码实例

from typing import List


class Solution:
    def longestMountain(self, A: List[int]) -> int:
        if not A:
            return 0
        n = len(A)
        # 左侧山脉
        left = [0] * n
        for i in range(1, n):
            left[i] = (left[i-1]+1 if A[i] > A[i-1] else 0)

		# 右侧山脉
        right = [0] * n
        for i in range(n-2, -1, -1):
            right[i] = (right[i+1]+1 if A[i+1] < A[i] else 0)
		
		# 记录山脉长度
        ans = 0
        for i in range(n):
            if left[i] > 0 and right[i] > 0:
                ans = max(ans, left[i]+right[i]+1)
        print(ans)
        return ans

if __name__ == '__main__':
    A = [2, 1, 4, 7, 3, 2, 5]
    obj = Solution()
    obj.longestMountain(A)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>