剣はオファー43を指します。1〜n整数に1の出現数(C ++)高低のアイデア

整数nを入力し、1からnまでのn個の整数の10進表現で1の出現回数を見つけます。
たとえば、12と入力すると、1から12までの整数に1を含む数字は、1、10、11、および12であり、1は合計5回表示されます。

例1:

输入:n = 12
输出:5

例2:

输入:n = 13
输出:6

制限:
1 <= n <2 ^ 31
注:この質問は、メインWebサイトの233の質問と同じです:https://leetcode-cn.com/problems/number-of-digit-one/

問題解決のアイデア:

ここに画像の説明を挿入します
特定の位置での1の発生数を計算する方法:

現在のビットの異なるcur値に応じて、次の3つの状況に分けることができます。

1. cur = 0の場合:このビット1の出現回数は、上位ビットの上位ビットによってのみ決定されます。計算式は、次の図に示すように、
上位×数字
です。n= 2304を例にとると、1を求めます。桁数= 10(つまり、10桁)出現回数。
ここに画像の説明を挿入します
2. cur = 1の場合:このビット1の出現回数は、上位ビットと下位ビットの下位によって決まります。計算式は、次の図に示すように、
high×digit + low +1
です。n= 2314を使用します。例として、digit = 10(つまり、10の位での1の出現回数)を見つけます。
ここに画像の説明を挿入します
3. cur = 2、3、...、9の場合:このビット1の出現回数は、上位ビットの上位ビットによってのみ決定されます。計算式は次のとおりです。

					(high+1)×digit

次の図に示すように、n = 2324を例にとると、1桁の数字= 10(つまり、10の位)の出現数を見つけます。
ここに画像の説明を挿入します
ここに画像の説明を挿入します

class Solution {
    
    
public:
    int countDigitOne(int n) {
    
    
        long digit = 1;
        int res = 0;
        int high = n / 10, cur = n % 10, low = 0;//cur是n除以10的余数,后面的cur是high的余数
        while(high != 0 || cur != 0) {
    
    // 当 high 和 cur 同时为 0 时,说明已经越过最高位,因此跳出
            if(cur == 0) res += high * digit;
            else if(cur == 1) res += high * digit + low + 1;
            else res += (high + 1) * digit;//
            low += cur * digit;//low就是cur一轮一轮叠加得到;此处参数是用作下一轮
            cur = high % 10;//cur是high的余数;;下一轮用
            high /= 10;//high从右边减少一位;下一轮用
            digit *= 10;//digit乘以10;下一轮用
        }
        return res;

    }
};

複雑さの分析:

時間計算量O(log n):ループ内の計算操作はO(1)時間を使用します。ループの数は、数値nの桁数、つまりlog 10 nであるため、ループはO(log n)を使用します。 )時間。
スペースの複雑さO(1):いくつかの変数は一定サイズの余分なスペースを使用します。

著者:jyd
リンク:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/mian-shi-ti-43-1n-zheng-shu -zhong-1-chu-xian-de-2 /
出典:LeetCode(LeetCode)
著作権は作者に帰属します。商用の転載の場合は、著者に連絡して許可を求め、非商用の転載の場合は、出典を示してください。

おすすめ

転載: blog.csdn.net/qq_30457077/article/details/114759466
おすすめ