特殊数组 II-LeetCode
3152. 特殊数组 II
🎯 问题描述
描述:
一个数组被称为特殊数组,如果它的每一对相邻元素的奇偶性都不同(即一个是奇数,一个是偶数)。
给你一个整数数组 nums 和一个二维整数数组 queries。
对于每个查询 queries[i] = [li, ri],你需要判断子数组 nums[li...ri] 是否是特殊数组。
返回一个布尔数组 answer,其中 answer[i] 为 true 表示该子数组是特殊的,否则为 false。
说明:
-
这是一个区间查询问题,核心在于判断区间内的相邻元素性质。
-
核心策略:
- 直接对每个查询遍历区间检查相邻元素会导致 的复杂度。
- 我们可以定义**“坏对”:指相邻两个元素奇偶性相同**的情况。
- 如果一个区间内“坏对”的数量为 0,则该区间是特殊的。
- 利用前缀和数组统计“坏对”的数量,实现 的查询。
-
示例:
-
示例 1:
1 | 输入:nums = [3,4,1,2,6], queries = |
💻 解题思路
思路1:前缀和统计“坏对”
核心逻辑
- 定义“坏对”:
- 对于下标
i,如果nums[i]和nums[i+1]的奇偶性相同(即(nums[i] & 1) == (nums[i+1] & 1)),则称(i, i+1)为一个“坏对”。
- 对于下标
- 构建前缀和数组
pref:pref[i]表示在nums[0...i-1]范围内(即前i个元素,涉及下标0到i-2的相邻对)存在的“坏对”总数。- 注意:你的代码中
pref的长度为n,且pref[i]实际上统计的是下标0到i-1这一对是否坏(或者是累积到位置i的坏对数)。 - 根据你的代码逻辑:
pref[i]存储的是从下标0到i-1这一段中,以i-1结尾的相邻对是否为坏对的累积值。 - 递推公式:
pref[i] = pref[i-1] + (1 if (nums[i-1] & 1) == (nums[i] & 1) else 0)。
- 处理查询:
- 对于查询
[l, r],我们需要检查的相邻对范围是(l, l+1)到(r-1, r)。 - 这些相邻对的“坏”状态被记录在
pref数组的相应位置。 - 利用前缀和差值:
pref[r] - pref[l]。pref[r]包含了直到下标r-1和r之间关系的累积(实际上你的代码逻辑中pref的定义略有不同,但差值逻辑是通用的)。- 你的代码逻辑解析:
pref[i]代表nums[0]...nums[i]中存在的坏对数量。- 查询
[l, r]涉及的对是(l, l+1)到(r-1, r)。 - 这些对的数量 =
pref[r] - pref[l]。 - 如果差值为 0,说明区间内没有坏对,返回
True。
- 对于查询
代码实现
1 | class Solution: |
📊 性能分析
- 时间复杂度:
- 构建前缀和数组:。遍历一次
nums。 - 处理查询:。每个查询只需 时间进行减法运算。
- 总体线性时间,非常高效。
- 构建前缀和数组:。遍历一次
- 空间复杂度:
- 需要一个长度为
n的pref数组。 - 结果数组
ans占用 空间。
- 需要一个长度为
思考
-
前缀和的定义细节:
- 你的代码中
pref[i]实际上表示的是nums[0]到nums[i]这一段中存在的坏对数量。 - 当
i=0时,没有相邻对,pref[0]=0。 - 当
i=1时,检查(0,1)是否坏对。 - 查询
[l, r]时,我们需要排除掉0到l之前的坏对,所以用pref[r] - pref[l]。
- 你的代码中
-
奇偶性判断:
- 代码使用
(nums[i] & 1)来判断奇偶性。 x & 1 == 1表示奇数,x & 1 == 0表示偶数。- 如果两个数奇偶性相同,它们的
& 1结果一定相等。
- 代码使用
-
为什么是
pref[r] - pref[l]?- 区间
[l, r]的相邻对是从索引l开始的(即(l, l+1))到索引r-1结束(即(r-1, r))。 pref[r]统计了直到(r-1, r)的所有坏对。pref[l]统计了直到(l-1, l)的所有坏对。- 相减正好去掉了
l之前的部分,留下了[l, r]区间内的坏对。
- 区间
-
边界情况:
- 如果
l == r,区间只有一个元素,没有相邻对,pref[r] - pref[l] = 0,返回True,逻辑正确。
- 如果
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






