leetcode 233. Number of Digit One

233. Number of Digit One

Total Accepted: 20083 Total Submissions: 79485 Difficulty: Hard

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时的情况总数。注意int的最大值:4294967296

对于特定的数n,设1出现的总次数为ones。从右向左的第i位(个位第1位)ni

(1) ni==0,ones+=n/10i+1*10i;

(2) ni==1,ones+=n/10i+1*10i+n%10i+1;

(3) ni>1,ones+=(n/10i+1+1)*10i;

代码:

基本的代码应该这样:

 1 class Solution {
 2 public:
 3     int countDigitOne(int n) {
 4         int a,b;
 5         long long ones=0;
 6         for(long long m=1;m<=n;m*=10){
 7             a=n/m;
 8             b=n%m;
 9             if(a%10==0){
10                 ones+=a/10*m;
11                 continue;
12             }
13             if(a%10==1){
14                 ones+=a/10*m+(b+1);
15                 continue;
16             }
17             ones+=(a/10+1)*m;
18         }
19         return ones;
20     }
21 };

下面用了一个技巧:ones+=(a+8)/10*m+(a%10==1)*(b+1)

 1 /*
 2 为什么m的类型为long long:因为m在最后1个循环后可能会超出int的范围。
 3 例如n=1410065408,如果m的类型是int,那么m=1000000000后,经过m*=10后,m溢出,m会仍然满足条件m<=n而继续循环。但这是不对的。所以m的类型要是long long。
 4 */
 5 class Solution {
 6 public:
 7     int countDigitOne(int n) {
 8         int a,b;
 9         long long ones=0;//显然,1的总和值可能会超过int的范围
10         for(long long m=1;m<=n;m*=10){
11             a=n/m;
12             b=n%m;
13             ones+=(a+8)/10*m+(a%10==1)*(b+1);
14         }
15         return ones;
16     }
17 };
原文地址:https://www.cnblogs.com/Deribs4/p/5624861.html