アルゴリズムは毎日の練習に質問します---72日目:数1の数

一緒に書く習慣をつけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して7日目です。クリックしてイベントの詳細をご覧ください

1.問題の説明

整数 を指定して、以下のすべて の非負の整数  の出現回数をnカウント します。n1

トピックリンク:番号1の数

第二に、主題の要件

例1

输入: n = 13
输出: 6
复制代码

例2

输入: n = 0
输出: 0
复制代码

訪問

1.数学思想、超时优化
2.建议用时15~35min
复制代码

3.問題分析

この質問を手にした途端、何かがおかしいと感じました。ループで数えるだけの非常に単純な質問でしたが、Likouは実際に難しいラベルを付けました。

class Solution {
public:
    int countDigitOne(int n) {
        int i,k,ans=0;//初始化数据
        for(i=1;i<=n;i++)//循环1~n
        {
            k=i;
            while(k)//数位中是否包含1
            {
                if(k%10==1)
                    ans++;//计数
                k=k/10;
            }
        }
        return ans;//输出结果
    }
};
复制代码

だから、私のコードは間違いなくタイムアウトします。

1.png

17.png

解決策>_<を読んだ後、これは通常の質問であることがわかりました。

2.png

ルールは次のとおりで、大物のアイデアを利用しています。

/**
从低往高位,计算每一位的数量:
第1位上的1的个数:1+(n-1)/10
第2位上的1的个数:(1+(n/10-1)/10)*10
第3位上的1的个数:(1+(n/100-1)/10)*100
……
第k+1位上的1的个数:(1+(n/(10^k)-1)/10)*(10^k)
如果n的第k+1位上是1,则说明可能没有填满该位,计算第k+1位的数量时还要 -10^k+1+n%(10^k),相当于独立计算
 */
复制代码

第四に、エンコーディングの実装

class Solution {
public:
    int countDigitOne(int n) {
        long long k = 1,ans = 0;//初始化数据
        while (n >= k){
            ans += (1+(n/k-1)/10)*k;//计数
            if (n/k%10 == 1) ans = ans-k+1+n%k;//当前位为1,减去数据
            k *= 10;
        }
        return ans;//输出结果
    }
};
复制代码

5.テスト結果

4.png

3.png

おすすめ

転載: juejin.im/post/7083646563754442783