233. Number of Digit One
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,然后统计剩下位数的数字中满足条件的可能情况数。其时间复杂度为O(log n).
考虑把某一个位的数字设成1后,分析他位置有多少种选择。然后把每个数字位取1而有的选择都加起来就可以了。
然后来分析其他位置有多少种选择: 假设为1350
(1) 如果将n的个位数置为1,xxx1
该位的数字置1之前为0, 所以从个位数往左边找需要减一的位,是十位数。找到减1的位之后,反过来把后面所有低位变为9,当前由于已经到个位了,所以没有体现出来。变为 0001 - 1341
card({000, 001...134}),满足条件的数共有135个
(2) 如果将n的十位数置为1,xx1x
该位的数字置1之前5>1,由于当前位1小于本来的5.所以 前面不需要减一,后面全部变为 9 。 0010 - 1319
card({000, 001...139}),共140个
(3) 如果将n的百位数置为1,x1xx
该位的数字置1之前3>1,由于当前位1小于本来的3.所以 前面不需要减一,后面全部变为 9. 0100
- 1199
2*card({00, 01...99}),共200个
(4) 如果将n的千位数置为1,1xxx
该位的数字置1之前=1,相等直接求 1000 -
1350
card({000,001...350}),共351个
于是所求的值count=135+140+200+351=826 个 1
class Solution {
public:
int countDigitOne(int n)
{
if (n <= 0) return 0;
else if (n < 10) return 1;
string s = to_string(n);
int ret = 0;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == '1')
{
ret += to_int(s.substr(0, i) + s.substr(i + 1)) + 1;
continue;
}
string ss = s;
int j = i;
if (s[i] == '0')
{
for (j = i - 1; j >= 0; j--) //往前面找需要减一的位
{
if (s[j] != '0')
{
ss[j] = ss[j] - 1;
break;
}
}
}
for (int h = j + 1; h < s.size(); h++) //在减一的位之后所有位都设为最大 ‘9’
ss[h] = '9';
ret += to_int(ss.substr(0, i) + ss.substr(i + 1)) + 1;
}
return ret;
}
int to_int(string s)
{
stringstream ss;
ss<<s;
int i;
ss>>i;
return i;
}
};
2531

被折叠的 条评论
为什么被折叠?



