剑指 Offer 43. 1~n 整数中 1 出现的次数(为什么是大数这边数的个数乘以小数边数的个数)
Posted 两片空白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 43. 1~n 整数中 1 出现的次数(为什么是大数这边数的个数乘以小数边数的个数)相关的知识,希望对你有一定的参考价值。
剑指 Offer 43. 1~n 整数中 1 出现的次数 https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
暴力解法:运用动态规划,从1到n,计算出每一个数i中1的个数countone,
dp[ i ]=dp[ i-1 ]+countone ,最后返回dp[ n ]。
class Solution {
public:
int countDigitOne(int n) {
if(n==0){
return 0;
}
vector<int> dp(n+1,0);
//初始化
dp[1]=1;
for(int i=2;i<=n;i++){
int count=0;
int x=i;
while(x){
if(x%10==1){
count++;
}
x/=10;
}
dp[i]=dp[i-1]+count;
}
return dp[n];
}
};
解法2:
计算1~n中数1的个数,可以转化位,计算1到n中的每个数中个位为1的时所有数的个数,十位为1时的所有数的个数,百位为1时的所有数的个数......所有位数1数的个数和。注意:是数的个数。
举一个例子:
有三种情况:
求哪一位1的个数,令这一位为1,然后取左右两边可能出现数的个数情况,然后相乘,就是这一位出现1的所有数的个数。注意 防止数超过本身n的值。
求的这一位的数值等于1
求的这一位数值小于1等于0。
求的这一位数值大于1。
class Solution {
public:
int countDigitOne(int n) {
//先从个位开始
long long base=1;
//结果
long long res=0;
//记录位值
int key=0;
while(base<=n){
long long a=n/base;
//base后面
long long b=n%base;
//位值
int key=a%10;
//base前面
a/=10;
//三种情况
if(key==0)
res+=a*base;
else if(key==1)
res+=(a*base+b+1);
else
res+=((a+1)*base);
//下一位
base*=10;
}
return res;
}
};
以上是关于剑指 Offer 43. 1~n 整数中 1 出现的次数(为什么是大数这边数的个数乘以小数边数的个数)的主要内容,如果未能解决你的问题,请参考以下文章
每日一题 - 剑指 Offer 43. 1~n整数中1出现的次数
剑指offer-面试题43-1~n整数中1出现的次数-归纳法