LeetCode 1523. 在区间范围内统计奇数数目
题目描述

题意分析
给定非负整数
low <= high,统计闭区间[low, high]中奇数的数量,两个端点都要参与判断。区间可能只包含一个数,也可能从零开始。范围较大,不需要逐个枚举,只需得到一个直接计数公式。
解法:前缀奇数计数公式
核心思路
[!blue]
从零开始,每两个连续整数组成一组,其中恰有一个奇数。若上界为偶数
2t,前缀里有t个奇数;若为奇数2t+1,则有t+1个。统一写成整数除法(high + 1) / 2。要保留
[low, high],应从这个前缀中去掉[0, low - 1]。把前缀公式的上界换成low - 1,奇数个数正好简化为low / 2。两者相减得到
(high + 1) / 2 - low / 2。当low = 0时,被去掉的前缀为空,对应数值也为零,因此无需实际计算负下标或额外分类。所有除法都作用于非负整数,截断与向下取整一致。
解题步骤
- 计算从零到右端点的奇数个数
(high + 1) / 2。- 计算左端点之前的奇数个数
low / 2。- 返回两者之差。
代码实现
class Solution {
public int countOdds(int low, int high) {
// (high+1)/2 是 [0, high] 内的奇数个数,low/2 是 [0, low-1] 内的奇数个数。
// 整数除法自动向下取整,四种奇偶组合无需分支。
return (high + 1) / 2 - low / 2;
}
}
func countOdds(low int, high int) int {
// (high+1)/2 是 [0, high] 内的奇数个数,low/2 是 [0, low-1] 内的奇数个数。
// 整数除法自动向下取整,四种奇偶组合无需分支。
return (high+1)/2 - low/2
}
复杂度分析
- 时间复杂度:$O(1)$,只做固定次数的整数运算。
- 空间复杂度:$O(1)$,不分配额外容器。
关键点总结
[!green]
- 闭区间计数等于右端前缀减去左端之前的前缀。
- 一条整数除法公式同时覆盖上下界的全部奇偶组合。
- 左端为零时空前缀贡献为零,单点区间也自然成立。
易错点总结
[!yellow]
- 使用
high / 2统计包含右端的前缀,会在右端为奇数时少算它。- 减去包含
low的前缀,会把合法左端点错误排除。- 只按区间长度除二后固定加一,无法同时处理两端的不同奇偶情况。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 303. 区域和检索 - 数组不可变 | 简单 | 同样把闭区间计数拆成两个前缀累计值之差,本题前缀奇数数量可以直接用整除公式求出。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!