2180. 统计各位数字之和为偶数的整数个数

文章提供了三种方法来计算从2到指定正整数num之间,各位数字之和为偶数的数的个数。解法一通过遍历并累加每位数字实现,时间复杂度为O(nlogn);解法二利用数学推导,根据个位数和前面数字之和的奇偶性判断,时间复杂度为O(logn);解法三同样基于数学分析,关注所有数之和的奇偶性,时间复杂度同样为O(logn)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解法一:模拟

222开始一直遍历到numnumnum, 对于每个数iii我们求得所有位上的数字之和。通过%10获取个位数字,再/10/10/10继续获取下一位,直到数为0停止循环。

  • 时间复杂度:O(nlogn)O(nlogn)O(nlogn), 其中n = num
  • 空间复杂度:O(1)O(1)O(1)
class Solution {
    public int countEven(int num) {
        int ans = 0, t, s;
        for (int i = 2; i <= num; i++) {
            for (s = 0, t = i; t > 0; t /= 10) s += t % 10; 
            ans += s & 1 ^ 1; // s & 1若为偶数则为0,若为奇数则为1, 再^1
        }
        return ans;
    }
}
class Solution {
public:
    int countEven(int num) {
        int ans = 0, t, s;
        for (int i = 2; i <= num; i++) {
            for (s = 0, t = i; t > 0; t /= 10) s += t % 10; 
            ans += s & 1 ^ 1;
        }
        return ans;
    }
};

解法二:数学推导

首先对于某个以0结尾的数如xyz0xyz0xyz0,到另外一个数xyzdxyzdxyzd之间的各位数字之和为偶数的正整数的数目,即区间[xyz0,xyzd][xyz0, xyzd][xyz0,xyzd],可以通过前面数字之和的奇偶和最后一位d来进行判断。


对于[0, d]中奇数的个数为(d+1)/2(d+1)/2(d+1)/2,偶数个数为d/2+1d/2 + 1d/2+1,令t = x+ y+z,即除个位数外,前面所有位之和,若t为奇数,则统计奇数个数;若t为偶数,则统计偶数个数。


接下来,我们计算[0,xyz0)[0, xyz0)[0,xyz0)区间满足要求的个数。我们设a=xyz0, 那么我们每次缩小区间为[a−10,a)[a - 10, a)[a10,a)直到缩小到[0, 10)停止。对于每个区间[a−10,a)[a-10, a)[a10,a)来说,满足要求的个数必然为5个,因为对于个位上的数可以取0,2,4,6,8和1,3,5,7,90,2,4,6,8和1,3,5,7,90246813579,而这样的区间个数位a/10a/10a/10,因此[0,a)[0, a)[0,a)满足要求的个数为a/10∗5a / 10 * 5a/105,由于我们求的是正整数,因此要减去一个0的答案。


综上所述,对于题目来说d=num % 10,a=num−dd = num\ \%\ 10, a = num - dd=num % 10,a=numd, 因此答案为ans=a∗/2−1+个数数匹配的答案数ans = a * / 2 - 1+个数数匹配的答案数ans=a/21+个数数匹配的答案数

  • 时间复杂度:O(logn)O(logn)O(logn)
  • 空间复杂度:O(1)O(1)O(1)
class Solution {
    public int countEven(int num) {
        int t, d = num % 10, a = num - d;
        for (t = 0, num = a; num > 0; num /= 10) t += num % 10;  
        return a / 2 - 1 + (t % 2 == 0 ? d / 2 + 1 : ++d / 2); 
    }
}
class Solution {
public:
    int countEven(int num) {
        int t, d = num % 10, a = num - d;
        for (t = 0, num = a; num > 0; num /= 10) t += num % 10;  
        return a / 2 - 1 + (t % 2 == 0 ? d / 2 + 1 : ++d / 2); 
    }
};

解法三:数学推导

首先我们从0到num,对于每个数i的所有位之和从偶奇..偶奇偶奇..偶奇偶奇..偶奇这样不断循环,当出现10个数后,顺序进行翻转变为奇偶奇偶奇偶奇偶奇偶奇偶,再过10个数继续翻转。 令t = num所有数为之和,通过分析可以发现,若t为偶数,答案为nums / 2nums\ /\ 2nums / 2, 若t为奇数,答案为(num−1) / 2(num - 1)\ /\ 2(num1) / 2

  • 时间复杂度:O(logn)O(logn)O(logn)
  • 空间复杂度:O(1)O(1)O(1)
class Solution {
    public int countEven(int num) {
        int t = 0;
        for (int j = num; j > 0; j /= 10) t += j % 10;  
        return t % 2 == 1 ? --num / 2 : num / 2;
    }
}
class Solution {
public:
    int countEven(int num) {
        int t = 0;
        for (int j = num; j > 0; j /= 10) t += j % 10;  
        return t % 2 == 1 ? --num / 2 : num / 2;
    }
};

如果有问题,欢迎评论区交流, 如果有帮助到你,请给题解点个赞和收藏哈~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值