算法 1~n中1的次数

输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。

示例 1:

输入:n = 12

输出:5

示例 2:

输入:n = 13

输出:6

原题出处:https://leetcode-cn.com/problems/number-of-digit-one/
算法1:把每个数字中包含1的数量计算出来,然后把1~n的1的数量全部加起来(效率低)

int NembOf1(int n)
{
    
    
	int ans = 0;
	while (n)
	{
    
    
		if (n % 10 == 1)
			ans++;
		n /= 10;
	}
	return ans;
}
int NembOf1BetweenN(int n)
{
    
    
	int ans = 0;
	for (int i = 1;i <= n;i++)
	{
    
    
		ans += NembOf1(i);
	}
	return ans;
}

算法2:看见他人分享的https://leetcode-cn.com/problems/number-of-digit-one/solution/c-kan-dao-bie-ren-fen-xiang-de-by-coke-10/.
编程之美上给出的规律: 1.如果第i位(自右至左,从1开始标号)上的数字为0,则第i位可能出现1的次数由更高位决定(若没有高位,视高位为0),等于更高位数字X当前位数的权重10^(i-1)。 2.如果第i位上的数字为1,则第i位上可能出现1的次数不仅受更高位影响,还受低位影响(若没有低位,视低位为0),等于更高位数字X当前位数的权重10^(i-1)+(低位数字+1)。 3.如果第i位上的数字大于1,则第i位上可能出现1的次数仅由更高位决定(若没有高位,视高位为0),等于(更高位数字+1)X当前位数的权重10^(i-1)。

通用结论:

从 1 至 10,在它们的个位数中,任意的 X 都出现了 1 次
从 1 至 100,在它们的十位数中,任意的 X 都出现了 10 次
从 1 至 1000,在它们的千位数中,任意的 X 都出现了 100 次
依此类推,从 1 至 10^i,在它们的左数第二位(右数第 i 位)中,任意的 X 都出现了10^(i−1) 次
得出的算法如下:

当计算右数第 i 位包含的 X 的个数时:

取第 i 位左边(高位)的数字,乘以 10^(i−1),得到基础值 a

取第 i 位数字,计算修正值:

如果大于 X,则结果为 a+10^(i−1)
如果小于 X,则结果为 a
如果等 X,则取第 i 位右边(低位)数字,设为 b,最后结果为 a+b+1

class Solution {
    
    
public:
    int countDigitOne(int n) {
    
    
        if(n<1) return 0;
        int res=0,digit=1;
        int right=0,now,left;
        while(n){
    
    
            now=n%10;
            left=n/10;
            if(now<1){
    
    
                res+=left*pow(10,digit-1);
            }
            else if(now==1){
    
    
                res+=left*pow(10,digit-1)+right+1;
            }
            else{
    
    
                res+=(left+1)*pow(10,digit-1);
            }
            right+=pow(10,digit-1)*now;
            digit++;
            n/=10;
        }
        return res;
    }
};


猜你喜欢

转载自blog.csdn.net/Gunanhuai/article/details/109263360