解法一:模拟
从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)[a−10,a)直到缩小到[0, 10)停止。对于每个区间[a−10,a)[a-10, a)[a−10,a)来说,满足要求的个数必然为5个,因为对于个位上的数可以取0,2,4,6,8和1,3,5,7,90,2,4,6,8和1,3,5,7,90,2,4,6,8和1,3,5,7,9,而这样的区间个数位a/10a/10a/10,因此[0,a)[0, a)[0,a)满足要求的个数为a/10∗5a / 10 * 5a/10∗5,由于我们求的是正整数,因此要减去一个0的答案。
综上所述,对于题目来说d=num % 10,a=num−dd = num\ \%\ 10, a = num - dd=num % 10,a=num−d, 因此答案为ans=a∗/2−1+个数数匹配的答案数ans = a * / 2 - 1+个数数匹配的答案数ans=a∗/2−1+个数数匹配的答案数
- 时间复杂度: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(num−1) / 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;
}
};
如果有问题,欢迎评论区交流, 如果有帮助到你,请给题解点个赞和收藏哈~~~