1.暴力
挨个遍历并判断该元素中2的个数,累加
超时
2.数学规律
思想是分类,先求所有书中个位是1的个数,再求十位是1的个数,依次类推
设n=xyzdabc,此时求千位,即d所在的位置,
则,分3中情况:
d<2,千位上2的个数是xyz*1000
d==2,千位是2的个数为xyz*1000+abc+1
d>2,千位是2的个数是xyz*1000+1000.
理由如下:
千位是2,即xyz2abc
对xyz,有0--xyz-1中取法,即xyz种
当xyz为上述其中一个数时,abc可以取0--999,即1000种,
此时有xyz*1000中可能
若d==2时,千位刚好是2,abc的值可以取到0--abc即,abc+1中,总为xyz*1000+abc+1
若d>2,d如果取2,abc可以取0--999,多了一千种可能,即总为xyz*1000+1000
求个位,十位,百位的原理类似
代码如下:
class Solution {
public:
int numberOf2sInRange(int n) {
int count = 0;
//依次考虑个位、十位、百位...是 2
for (int k = 1; k <= n; k *= 10) {
// xyzdabc
int abc = n % k;
int xyzd = n / k;
int d = xyzd % 10;
int xyz = xyzd / 10;
count += xyz * k;
if (d > 2) {
count += k;
}
if (d == 2) {
count += abc + 1;
}
//如果不加这句的话,虽然 k 一直乘以 10,但由于溢出的问题
//k 本来要大于 n 的时候,却小于了 n 会再次进入循环
//此时代表最高位是 1 的情况也考虑完成了
if(xyz == 0){
break;
}
}
return count;
}
};