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
共hightest−1个完整区间,代码中的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∗(1000−nums([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;
}
}
效率 秒