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

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

题目描述

给你一个正整数 num ,请你统计并返回 小于或等于 num 且各位数字之和为 偶数 的正整数的数目。
正整数的 各位数字之和 是其所有位上的对应数字相加的结果。

示例 1:

输入:num = 30
输出:14
解释:
只有 14 个整数满足小于等于 30 且各位数字之和为偶数,分别是:
2、4、6、8、11、13、15、17、19、20、22、24、26 和 28 。

提示:

  • 1 <= num <= 1000

直接翻译成数学题

给你一个数num,求满足条件的i的个数。其中 i < = 1000 , i ∈ [ 1 , 2 , . . . , n u m s ] , ∑ j = 0 j < l e n ( i ) b i t ( i , j ) i<=1000, i\in [1,2,...,nums], \sum_{j=0}^{j<len(i)} bit(i,j) i<=1000,i[1,2,...,nums],j=0j<len(i)bit(i,j)为偶数。 b i t ( ) , l e n ( ) , ∑ bit(),len(),\sum bit(),len(),含义详见下方代码


解决方案一 字符串简单模拟

i ∈ [ 0 , 1 , 2 , . . . , n u m s ] i\in [0,1,2,...,nums] i[0,1,2,...,nums]

for(int i=1;i<=nums;i++);

l e n ( i ) len(i) len(i)

String.valueOf(i).length();

bit(i,j) 获取整数i的第j位数字(从地位开始)

String.valueOf(i).charAt(j)-'0';

$\sum_{j=0}^{j<len(i)}bit(i,j) $ : 求i各个 位上 的数字之和

int sum = 0;
String stringI = String.valueOf(i);
for(int j=0;j<length;j++){
    sum = sum + stringI.charAt(j)-'0';
}

i ∈ [ 1 , 2 , . . . , n u m s ] , ∑ j = 0 j < l e n ( i ) b i t ( i , j ) i\in [1,2,...,nums], \sum_{j=0}^{j<len(i)} bit(i,j) i[1,2,...,nums],j=0j<len(i)bit(i,j)

int count = 0;
for(int i=1;i<=num; i++){
    String stringI = String.valueOf(i);
    int length = stringI.length();
    int sum = 0;
    for(int j=0;j<length;j++){
        sum = sum + stringI.charAt(j)-'0';
    }
    if(sum%2==0){
        count++;
    }
}
return count;

算法效率

在这里插入图片描述


解决方案二 子问题求解

先说人话

ℹ️对应下面性质1: [100,199]中偶数个数+[200,299]中偶数个数=100,[3000,3999]中偶数个数+[4000,4999]中偶数个数=1000

ℹ️对应下面性质2: [200,299]中偶数个数=[0,99]中偶数个数,[3000,3999]中偶数个数=1000-[0,999]中偶数个数(结合第一点)

ℹ️ 对应下面性质3: i = 6453 i=6453 i=6453,其完整区间 [ 1000 , 1999 ] , [ 2000 , 2999 ] , . . . , [ 5000 , 5999 ] [1000,1999],[2000,2999],...,[5000,5999] [1000,1999],[2000,2999],...,[5000,5999],如果最高位是奇数,则有偶数个完整区间,如果最高位是偶数,则有奇数个完整区间,且最后一个完整区间是奇数(这里是5)开头

翻译成数学语言

ℹ️性质1:对于整数 i = 2 X 1 X 2 i=2X_1X_2 i=2X1X2,如果 i i i的各 位数 之和是偶数 ( 2 + X 1 + X 2 是偶数 ) (2+X_1+X_2是偶数) (2+X1+X2是偶数),则 3 X 1 X 2 3X_1X_2 3X1X2的各 位数 之和必然是奇数
⟹ \Longrightarrow $A=[200_偶,201_奇,…,299_偶] $
B = [ 30 0 奇 , 30 1 偶 , . . . , 39 9 奇 ] , 则集合 A B=[300_奇,301_偶,...,399_奇], 则集合A B=[300,301,...,399],则集合A中所有元素的各 位数 之和是偶数的个数 + B +B +B集合中所有元素的各 位数 之和是偶数的个 数 $=100 $

ℹ️性质2:对于整数 i = 2 X 1 X 2 i=2X_1X_2 i=2X1X2, 其奇偶性与 X 1 , X 2 X_1,X_2 X1,X2相同, ⟹ [ 200 , 201 , . . . , 299 ] 中各位数之和为偶数的个数 = [ 0 , 1 , 2 , . . . , 99 ] \Longrightarrow [200,201,...,299]中各 位数 之和为偶数的个数=[0,1,2,...,99] [200,201,...,299]中各位数之和为偶数的个数=[0,1,2...,99]中各 位数 之和为偶数的个数。
对于整数 i = 3 X 1 X 2 i=3X_1X_2 i=3X1X2, 其奇偶性与 X 1 , X 2 X_1,X_2 X1,X2相反, ⟹ [ 300 , 301 , . . . , 399 ] \Longrightarrow [300,301,...,399] [300,301,...,399]中各 位数 之和为偶数的个数 = 1 , 00 − [ 0 , 1 , 2 , . . . , 99 ] =1,00 -[0,1,2,...,99] =1,00[0,1,2...,99]中各 位数 之和为偶数的个数(结合性质1)

ℹ️ 性质3:整数 i i i,其最高位值为hightest,则至少存在$[10…0, 10…1, …, 19…9], [20…0,20…0,…, 29…9]…[(hightest-1)0…0, (hightest-1)0…1,…, (hightest-1)9…9] $ 共 h i g h t e s t − 1 共hightest-1 hightest1个完整区间,代码中的fullSection

对于整数 i = 4 X 1 X 2 X 3 i=4X_1X_2X_3 i=4X1X2X3
1️⃣ [ 1000 , 1001 , . . . , 1999 ] , [ 2000 , 2001 , . . . , 2999 ] [1000,1001,...,1999],[2000,2001,...,2999] [1000,1001,...,1999],[2000,2001,...,2999] 各 位数 之和为偶数的个数共1000个。
2️⃣ [ 3000 , 3001 , . . . , 3999 ] 与 [ 0 , 999 ] [3000,3001,...,3999]与[0,999] [3000,3001,...,3999][0,999] 共1000个
3️⃣ [ 4000 , 4001 , . . . , 4 X 1 X 2 X 3 ] [4000,4001,...,4X_1X_2X_3] [4000,4001,...,4X1X2X3] [ 0 , 1 , . . . , X 1 X 2 X 3 ] [0,1,...,X_1X_2X_3] [0,1,...,X1X2X3]相同

⟹ \Longrightarrow n u m s ( [ 0 , 1 , . . . , 4 X 1 X 2 X 3 ] ) = 2 ∗ ( 1000 − n u m s ( [ 0 , 1 , . . . 999 ] ) ) + n u m s ( [ 0 , 1 , . . . , 999 ] ) + n u m s ( [ 0 , 1 , . . . , X 1 X 2 X 3 ] ) nums([0,1,...,4X_1X_2X_3]) = 2*(1000-nums([0,1,...999]))+nums([0,1,...,999])+nums([0,1,...,X_1X_2X_3]) nums([0,1,...,4X1X2X3])=2(1000nums([0,1,...999]))+nums([0,1,...,999])+nums([0,1,...,X1X2X3])

代码根据以独自考虑最高位为奇数时的情形

理论完毕 上菜

public static int countEven(int num) {
    if (num < 10) {
        return num/2;
    }
    String numStr = String.valueOf(num);
    int length = numStr.length();
    int weight = (int) Math.pow(10, length - 1);
    int highest = numStr.charAt(0) - '0';
    int fullSection = highest - 1;
    int sum = fullSection/2*weight;
    int y = num - num / weight * weight;
    // fullSection为奇数,则hightest必定为偶数
    if ((fullSection & 1) == 1) {
        int remain = countEven(y);
        int result = sum + weight +remain ;
        return result;
    }else{
        int result  = sum + countEven(weight - 1) + (y - countEven(y));
        return result;
    }
}

效率 秒

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值