LeetCode845. 数组中的最长山脉(双指针技巧)

1、题目描述

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。

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

2、代码详解

法一:双指针,中心向两侧扩张

剪枝前

class Solution(object):
    def longestMountain(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        n = len(A)
        if not A or n <= 2:
            return 0
        n_max = 0

        for i in range(1, n-1):  #
            if A[i-1] < A[i] and A[i] > A[i+1]:
                left = i - 1  # 以i为山顶的左山底
                right = i + 1  # 以i为山顶的右山底
                while left > 0 and A[left-1] < A[left]:  # 向左找山底
                    left -= 1
                while right < n-1 and A[right+1] < A[right]:  # 向右找山底
                    right += 1
                    
                n_max = max(n_max, (right-left+1))

        return n_max

剪枝后(i可以直接移到right位置)

class Solution(object):
    def longestMountain(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        n = len(A)
        if not A or n <= 2:
            return 0
        n_max = 0
        i = 1  # 剪枝
        while i < n-1:  # 剪枝
            if A[i-1] < A[i] and A[i] > A[i+1]:
                left = i - 1  # 以i为山顶的左山底
                right = i + 1  # 以i为山顶的右山底
                while left > 0 and A[left-1] < A[left]:  # 向左找山底
                    left -= 1
                while right < n-1 and A[right+1] < A[right]:  # 向右找山底
                    right += 1
                n_max = max(n_max, (right-left+1))
                i = right  # 剪枝
            else:
                i += 1  # 剪枝
        return n_max

时间复杂度小于O(n*n),这种做法也是O(n)的,因为那种有n个数量级的点都可能成为答案的时候,左右能扩出去的长度是很有限的。每个点也只会被访问有限次

法二:左右双指针,正序遍历一次,逆序遍历一次

山脉的长度为 left+right[i]+1

枚举山顶 https://leetcode-cn.com/problems/longest-mountain-in-array/solution/shu-zu-zhong-de-zui-chang-shan-mai-by-leetcode-sol/

class Solution(object):
    def longestMountain(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        if not A:
            return 0
        n = len(A)
        left = [0] * n
        for i in range(1, n):
            if A[i] > A[i-1]:
                left[i] = left[i-1] + 1
            else:
                left[i] = 0
        right = [0] * n
        for i in range(n-2, -1, -1):
            if A[i] > A[i+1]:
                right[i] = right[i+1] + 1
            else:
                right[i] = 0
        n_max = 0
        print(left)
        print(right)
        for i in range(n):
            if left[i] > 0 and right[i] > 0:
                n_max = max(n_max, left[i]+right[i]+1)
        return n_max
  • 时间复杂度:O(n),其中 n 是数组长度
  • 空间复杂度:O(n),即为数组left 和right 空间
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值