剑指offer 整数中1出现的次数(从1到n整数中1出现的次数)

Posted qinduanyinghua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer 整数中1出现的次数(从1到n整数中1出现的次数)相关的知识,希望对你有一定的参考价值。

题目描述

求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
 
思路一:计算区间内每个数含有1的个数,并累加起来。
 1 class Solution 
 2 private:
 3     int NumberOf1(unsigned int n) 
 4         int cnt = 0;
 5         while (n) 
 6             if (n % 10 == 1) 
 7                 cnt++;
 8             
 9             n /= 10;
10         
11         return cnt;
12     
13 public:
14     int NumberOf1Between1AndN_Solution(int n)
15     
16         int number = 0;
17         for (unsigned int i = 1; i <= n; ++i) 
18             number += NumberOf1(i);
19         
20         return number;
21     
22 ;

思路二:利用数学归纳法,直接对n进行分析,归纳总结规律

例如n=abcde五位数,我们分析百位的c,主要有以下三种情况:

1)当c == 0的时候,比如13013,此时百位出现1的是:00 100 ~ 00 199, 01 100~01 199,……,11 100~ 11 199,12100~12199共1300个,显然这个由高位数字决定,并且受当前位数影响,结果为:(高位数字)乘以(当前位数);
2)当c == 1的时候,比如13113,此时百位出现1的肯定包括c=0的情况,另外还需要考虑低位的情况即:00100 ~ 00113共114个,结果为:(高位数字)乘以(当前位数)+(低位数字)+1;
3)当c >= 2的时候,比如13213,此时百位出现1的是:00 100 ~ 00 199, 01 100~01 199,……,11 100~ 11 199,12 100 ~ 12 199,13100~13199,共1400个,这个仅由高位数字决定,结果为:(高位数字+1)乘以当前位数。

 1 class Solution 
 2 public:
 3     int NumberOf1Between1AndN_Solution(int n)
 4      
 5         long long lower, higher, cur;
 6         long long cnt = 0;
 7         long long factor = 1;
 8         for (int i = 1; i <= n; i *= 10) 
 9             lower = n % i;
10             higher = n / (i * 10);
11             cur = (n / i) % 10;
12             if (cur == 0) 
13                 cnt += higher * i;
14              else if (cur == 1) 
15                 cnt += higher * i + lower + 1;
16              else 
17                 cnt += (higher + 1) * i;
18             
19         
20         return cnt;
21     
22 ;

思路三:数位dp (正在学习中)

 1 class Solution 
 2     public:
 3         int dp[30][30];
 4         int digit[30];
 5         
 6         int dfs(int l, int cnt, bool flag) 
 7             if (l == 0) return cnt;
 8             if (!flag && ~dp[l][cnt]) return dp[l][cnt];
 9             int pos = flag ? digit[l] : 9;
10             int ret = 0;
11             for (int i = 0; i <= pos; i++) 
12                 ret += dfs(l - 1, cnt + (i == 1), flag && (pos ==i));
13             
14             if (!flag) dp[l][cnt] = ret;
15             return ret;
16         
17         
18         int countDigitOne(int n) 
19             memset(dp, -1, sizeof(dp));
20             int pos = 0;
21             while(n) 
22                 digit[++pos] = n % 10;
23                 n /= 10;
24             
25             return dfs(pos, 0, true);
26         
27 ;

 

以上是关于剑指offer 整数中1出现的次数(从1到n整数中1出现的次数)的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer整数中1出现的次数(从1到n整数中1出现的次数)

剑指offer:整数中1出现的次数(从1到n整数中1出现的次数)

整数中1出现的次数(从1到n整数中1出现的次数)-剑指Offer

剑指offer--整数中1出现的次数(从1到n整数中1出现的次数)

[剑指offer]整数中1出现的次数(从1到n整数中1出现的次数)

剑指offer 整数中1出现的次数(从1到n整数中1出现的次数)