您的位置:首页 > 其它

Number of Digit One(leetcode 233)

2015-07-11 19:56 447 查看
Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.

For example:

Given n = 13,

Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.

1。 最笨方法, 从1到n,看一看每个数有多少个1,最后相加。超时

2。 有规律的

一位数中1个数 1

两位数中1个数 一位数*10 + 一位数个数(10的一次方)

三位数中1个数 两位数*10 + 两位数个数(10的二次方)

如果某一位为0 跳过

为1 为低位数的和+1

》=2 为 n*第几位

。。。。。。。。。。。。。。

对整数 abcdef

就是 0-f 中 1 + 0-e*10 中1 + 0- c* 10* 10 中1 。。。

class Solution {
public:
int countDigitOne(int n) {
if (n <= 0) {
return 0;
}
vector<int> c;   // c[1]   一位数中1的个数
// c[2]  两位数中1个数   。。。。。
vector<int> num;    //输入的数转化为倒序int数组
int total = 0;
c.push_back(0);
c.push_back(1);  // 0-9
// 将数打散
while (n != 0) {
int t = n % 10;
num.push_back(t);
n = n / 10;
}
// 计算几位数应该有多少个1
for(int i = 2; i < num.size(); ++i) {
c.push_back(10*c[i-1] + gen10(i - 1));
}
for(int j = 0; j < num.size(); ++j) {
total = total + (num[j]) * c[j];
// 大于1
if (num[j] > 1) {
total += gen10(j);
}
// 为1
if (num[j] == 1) {
int tmp = 0;
for (int k = j - 1; k >= 0; --k) {
tmp = tmp * 10 + num[k];
}
total += tmp;
total += 1;
}
}
return total;
}
// 10的多少次方
int gen10(int i) {
int t = 1;
for(int j = 0; j < i; ++j) {
t*= 10;
}
return t;
}
};


网上同样思路,不过公式化

以算百位上1为例子: 假设百位上是0, 1, 和 >=2 三种情况:

case 1: n=3141092, a= 31410, b=92. 计算百位上1的个数应该为 3141 *100 次.

case 2: n=3141192, a= 31411, b=92. 计算百位上1的个数应该为 3141 *100 + (92+1) 次.

case 3: n=3141592, a= 31415, b=92. 计算百位上1的个数应该为 (3141+1) *100 次.

以上三种情况可以用 一个公式概括:

(a + 8) / 10 * m + (a % 10 == 1) * (b + 1)

public class Solution {
public int countDigitOne(int n) {
int ones = 0;
for (long m = 1; m <= n; m *= 10) {
long a = n/m, b = n%m;
ones += (a + 8) / 10 * m;
if(a % 10 == 1) ones += b + 1;
}
return ones;
}
}


http://www.2cto.com/kf/201507/415690.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: