LeetCode:795(Python)—— 区间子数组个数(中等)

区间子数组个数

概述:给你一个整数数组 nums 和两个整数:left right 。找出 nums 中连续、非空且其中最大元素在范围 [left, right] 内的子数组,并返回满足条件的子数组的个数。

输入:nums = [2,1,4,3], left = 2, right = 3
输出:3
解释:满足条件的三个子数组:[2], [2, 1], [3]

输入:nums = [2,9,2,5,6], left = 2, right = 8
输出:7

方法一:双指针

思路:本题可以转换为求解不包含 >right,且至少包含一个 <=right 的子数组数目。所以分别建立快慢指针来表示范围,最后输出快慢指针的差即可。

# 双指针
# 本题可以转换为求解不包含 >right,且至少包含一个 <=right 的子数组数目。
# 所以分别建立快慢指针来表示范围,最后输出快慢指针的差即可。
class Solution:
    def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int:
        ans, slow, fast = 0, -1, -1
        for i, v in enumerate(nums):
            if left <= v <= right:
                slow = i
            elif v > right:
                fast = i
                slow = -1
            if slow != -1:
                ans += slow - fast
        return ans

方法二:计数法

思路:思路和上面一致,不同在于定义一个计数函数,最后输出即可。

# 计数法
# 思路和上面一致,不同在于定义一个计数函数,最后输出即可。
class Solution:
    def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int:
        def count(lower: int) -> int:
            ans = cur = 0
            for num in nums:
                if num <=lower:
                    cur += 1
                else:
                    cur = 0
                ans += cur
            return ans
        return count(right) - count(left - 1)

方法三:单调栈

思路:利用栈的特点统计出所有边界点,然后删除重复统计即可。

# 单调栈
# 利用栈的特点统计出所有边界点,然后删除重复统计即可。
class Solution:
    def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int:
        ans, n = 0, len(nums)
        left_list, right_list = [-1] * n, [n] * n
        stack = []
        for i in range(n):
            while stack and nums[stack[-1]] < nums[i]:
                right_list[stack.pop()] = i
            stack.append(i)
        stack = []
        for i in range(n - 1, -1, -1):
            while stack and nums[stack[-1]] <= nums[i]:
                left_list[stack.pop()] = i
            stack.append(i)
        for i in range(n):
            if left <= nums[i] <= right:
                ans += (i - left_list[i]) * (right_list[i] - i)
        return ans

总结

思路还算能想到,但是处理边界恶心死了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值