每日leetcode

1523. 在区间范围内统计奇数数目 - 力扣(LeetCode)

题目

给你两个非负整数 low 和 high 。请你返回 low  high 之间(包括二者)奇数的数目。

示例 1:

输入:low = 3, high = 7
输出:3
解释:3 到 7 之间奇数数字为 [3,5,7] 。

示例 2:

输入:low = 8, high = 10
输出:1
解释:8 到 10 之间奇数数字为 [9] 。

提示:

  • 0 <= low <= high <= 10^9

思路

  1. 该题可以化简为两个奇数(包含他们本身)之间包含多少个奇数,因为上下界可以直接通过加减1来收缩到奇数的范围。
  2. 那么就需要考虑两个奇数间隔某一长度是否可以通过某个通项公式求得奇数个数。
  3. 那我们看看中间会有多少对奇偶数对,当high和low都是奇数时,(high-low)/2即是除low之外的奇偶数对数,那么我们再补上low的1即可。
  4. 最后就只要考虑怎么变成双奇数的情况即可,考虑以下几个情况:
    1. 当low==high,若是奇数就是1,偶数就是0,那么结果就是low%2。
    2. 当high-low==1,那么必为一奇一偶,结果直接就是1。
    3. 剩下的情况直接low为偶就加1,high为偶就减1,其他情况不变。

代码实现

class Solution {
public:
    int countOdds(int low, int high) {
        if(low == high) return low % 2;
        if(high - low == 1) return 1;
        if(high % 2 == 0) --high;
        if(low % 2 == 0) ++low;
        return (high-low)/2+1;
    }
};

复杂度分析

  • 时间复杂度:O(1)。
  • 空间复杂度:O(1)。

题解

  • 官方题解给出的是一种前缀和的做法,那么就转化为[0, high]的奇数个数减去[0,low)(即[0, low-1])的奇数个数。
  • 那么这个前缀和的奇数个数怎么算呢?还是变成求奇偶数对的个数,假设上界x为奇数,那么奇偶数对个数为(x+1)/2,假设上界x为偶数,为x/2,但是因为int的截断逻辑,所以也可以是(x+1)/2,所以那么求前缀和就可以变为(x+1)/2,通过位运算加速则可以变成(x+1)>>1。
  • 复现:
  • class Solution {
    public:
        int pre(int x) {
            return (x+1) >> 1;
        }
        int countOdds(int low, int high) {
            return pre(high)-pre(low-1);
        }
    };

你可能感兴趣的:(leetcode训练,leetcode,算法,数据结构,c++,职场和发展)