1. 题目解析:区间子数组个数问题
这道题目要求我们统计数组中所有连续子数组的最大值落在给定区间内的数量。乍一看可能觉得需要枚举所有子数组然后检查最大值,但对于长度为10^5的数组来说,O(n^2)的暴力解法显然不可行。我们需要找到更聪明的解法。
1.1 问题重述与理解
给定一个整数数组nums和两个整数left、right,我们需要找出所有连续非空子数组,这些子数组的最大元素值在[left, right]范围内。例如:
对于nums = [2,1,4,3],left=2,right=3:
- [2]:最大值2 ∈ [2,3] → 符合
- [2,1]:最大值2 ∈ [2,3] → 符合
- [1]:最大值1 ∉ [2,3] → 不符合
- [4]:最大值4 ∉ [2,3] → 不符合
- [3]:最大值3 ∈ [2,3] → 符合
所以总共有3个符合条件的子数组。
1.2 暴力解法的局限性
最直观的解法是枚举所有可能的子数组,然后检查每个子数组的最大值是否在指定范围内。对于一个长度为n的数组,子数组数量为n*(n+1)/2,时间复杂度为O(n^2)。当n=10^5时,这样的解法显然会超时。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 双指针解法思路
2.1 核心观察
关键观察点是:我们可以将问题转化为计算"所有子数组的最大值不超过right"的数量减去"所有子数组的最大值小于left"的数量。这样就将原问题分解为两个更简单的子问题。
2.2 双指针策略
我们使用两个指针minStart和maxStart来跟踪当前子数组的起始范围:
- minStart:当前子数组可以开始的最小下标
- maxStart:当前子数组可以开始的最大下标(即最后一个满足条件的元素位置)
对于每个元素nums[i],我们分三种情况处理:
- nums[i]在[left, right]范围内:可以扩展有效子数组范围
- nums[i] < left:可以包含在子数组中,但不影响最大值
- nums[i] > right:必须排除,重置指针位置
2.3 算法流程详解
初始化:
- count = 0(记录符合条件的子数组数量)
- minStart = 0
- maxStart = -1(初始无效值)
遍历数组:
- 如果nums[i] >
