演算法 1~n中1的次數

_MaL發表於2020-10-24

輸入一個整數 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;
    }
};


相關文章