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

来源:力扣(LeetCode)

描述:

给你一个正整数 num ,请你统计并返回 小于或等于 num 且各位数字之和为 偶数 的正整数的数目。

正整数的 各位数字之和 是其所有位上的对应数字相加的结果。

示例 1:

输入:num = 4
输出:2
解释:
只有 24 满足小于等于 4 且各位数字之和为偶数。   

示例 2:

输入:num = 30
输出:14
解释:
只有 14 个整数满足小于等于 30 且各位数字之和为偶数,分别是: 
246811131517192022242628

提示:

  • 1 <= num <= 1000

方法一:暴力枚举

  枚举位于区间 [1,num] 内的所有正整数,如果正整数的各位数字之和为偶数,那么将结果加 1,最后返回结果。

代码:

class Solution {
public:
    int countEven(int num) {
        int res = 0;
        for (int i = 1; i <= num; i++) {
            int x = i, sum = 0;
            while (x) {
                sum += x % 10;
                x /= 10;
            }
            if (sum % 2 == 0) {
                res++;
            }
        }
        return res;
    }
};

执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.7 MB, 在所有 C++ 提交中击败了83.66%的用户
复杂度分析
时间复杂度:O(num×lognum)。我们总共需要枚举 num 个正整数,而判断每个正整数的各位数字之和是否为偶数需要 O(lognum) 的时间复杂度。
空间复杂度:O(1)。

方法二:数学

首先有两个简单的数学结论:

  • 给定 0 ≤ x < 10,位于区间 [0, x] 内的偶数个数为 ⌊ x / 2 ⌋ + 1,位于区间 [0, x] 内的奇数个数为 ⌊ x / 2 ⌋。
  • 位于区间 [0, 10) 的奇数和偶数的个数都是 5 个。

我们将 num 表示为 10 × y + x 的形式,其中 0 ≤ x < 10 且 y ≥ 0,那么位于区间 [0, num] 的整数可以分为两个部分:

  • 区间 [10 × y + 0, 10 × y + x]:
    • 如果 y 的各位数字之和为偶数,那么该区间内各位数字之和为偶数的整数个数为 ⌊ x / 2 ⌋ + 1;
    • 如果 y 的各位数字之和为奇数,那么该区间内各位数字之和为偶数的整数个数为 ⌊ x / 2 ⌋。
  • 区间 [0,10 × y + 0):
    • 注意到该区间的数可以表示为 10 × t + g 的形式,其中 0 ≤ t < y 且 0 ≤ g < 10。固定住 t 时,如果 t 的各位数字之和为偶数,那么 g 为偶数的取值数目为5,奇数时类似,因此该区间内的各位数字之和为偶数的整数个数为 y × 5。

注意到上述区间中我们多计入了整数 0,因此结果应该是位于上述区间且各位数字之和为偶数的个数减 1。

代码:

class Solution {
public:
    int countEven(int num) {
        int y = num / 10, x = num % 10;
        int res = y * 5, ySum = 0;
        while (y) {
            ySum += y % 10;
            y /= 10;
        }
        if (ySum % 2 == 0) {
            res += x / 2 + 1;
        } else {
            res += (x + 1) / 2;
        }
        return res - 1;
    }
};

执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.8 MB, 在所有 C++ 提交中击败了67.82%的用户
复杂度分析
时间复杂度:O(lognum)。
空间复杂度:O(1)。
author:LeetCode-Solution

你可能感兴趣的:(LeetCode,leetcode,算法,c++,数据结构)