旧魏は、タイトルシリーズ---ブラシ(整数31 1が表示されます)を学ぶためにあなたを取るために提供を受賞します

31.整数1現れます

問題:

番号1が表示さは1-13の整数で決定され、出現1の整数で100から1300までの数を計算しますか?この目的を達成するために、彼は特に1-13は、数字1が含まれています数え1,10,11,12,13は、したがって、6回の合計を表示されますが、彼Meizhe後ろの問題のためにしています。ACMerは、範囲内の負でない整数の数1が表示され、あなたは彼を助けることを願っていますし、問題がより一般化された(1からnまでの発生回数。1)迅速いずれかを見つけることができます。

ソリューション:

同様のこのような問題は、我々は、関連するものを取得することによって要約することができます。

まず、あなたは最初のカテゴリを次のことができます。

ビット
我々が一桁に知っている、1等毎に10、11、21、一旦発生する例えば、我々は、ラダーとして10は、次いで、各々が1内部完全ラダーを有することを見出し例えば数字22用、3段階の間隔で10ポイントに応じて、完全な梯子に0-9,10-19は1を持っていますが、不完全なラダーが19後があり、我々はこのはしごを判断するために必要なのは1には表示されません1未満にさらされ、この最後の部分は、それが1不可能であれば簡単な推論を知るためには、(これを行うためにまとめたも他の図についても同様です)。

我々は1が表示され、次のようにビット数に一般化することができます:

n/10 * 1+(n%10!=0 ? 1 : 0)

テンは
今も使用ラダー理論的な一桁の時に、私たちは数字10-19、100のこのセットは毎回起こることを知っている、10桁の場合1が表示されますが、10-19である必要があり、10桁の数字を言います我々のラダー100、317は、デジタル解析、ステップラダー0-99,100-199,200-299完全三つのセクション、10回1(10-19から)表示されるラダーの各セクションは、最終的な分析が明らかにされていますその不完全はしごの間に。10-19が存在しますので、私たちは、ライン上で、その後の直接数10 1、数が19以上である場合にはさらさ考えられ、10未満の場合、それは確かに1の数十は表示されません。10-19間の場合10 + 1 -我々は結果をkであるべき計算します。たとえば、私たちは300-317,17番号を解析し、数1は17-10 + 1 = 8を表示されます。

現在では、要約することができます。10数1が表示されます上で次のように:

设k = n % 100,即为不完整阶梯段的数字
归纳式为:(n / 100) * 10 + (if(k > 19) 10 else if(k < 10) 0 else k - 10 + 1)

百は
今、私たちは百、百1 100-199が表示されますで、100回の合計が登場することを知って、百1と言う、1000,100-199数字のこのセットを間隔を強化、1000年には毎回表示されます。私たちは、この数は2139であることを前提としています。上記の考えと一致して、上記に従う、その後カウントはその後、部分139を脱出百のステップ1 *完全な番号が表示され、最初の二つのステップ1で得られた、すなわち、N / 1000 * 100の数、工程数をカウントします100 + 1%のビット-思考、不完全ラダーk199の数百100 1100 <= K <= 199が得られるKを得ました。

そして、百数に1が表示されますを要約し続けます。

设k = n % 1000
归纳式为:(n / 1000) * 100 + (if(k >199) 100 else if(k < 100) 0 else k - 100 + 1)

バックのように...

再びビットを想起
一桁の番号への私たちの式は、誘導式に取得するために含まれています

k = n % 10
个位数上1的个数为:n / 10 * 1 + (if(k > 1) 1 else if(k < 1) 0 else k - 1 + 1)

パーフェクト!誘導性は非常に構造化しているようです。より抽象的に加算され、iは1が1の桁数、10の意味の計算は、10桁の数字が算出されることを示す、など=ビットI 1の数を計算するために設けられています。

k = n % (i * 10)
count(i) = (n / (i * 10)) * i + (if(k > i * 2 - 1) i else if(k < i) 0 else k - i + 1)

まあ、そう誘導10-10からのn乗が完了していること。

sum1 = sum(count(i)),i = Math.pow(10, j), 0<=j<=log10(n)

しかし、我々の注目に値する場所は、ビューのコードポイントのシンプルであり、より多くのifelseは非常に良いではありませんがある、それをさらに簡素化することができますか?1、我々はKのみを確認する必要があります - - 私たちは、私は* 2を計算していない、そのような方法で、後半を簡素化することができますI + 1 [0、i]はライン間隔で、本の最後の半分の後に書き込むことができます

min(max((n mod (i*10))−i+1,0),i)

Pythonコード:

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        i = 10 ** (len(str(n))-1)
        count = 0
        while i != 0:
            k = n % (10 * i)   ##计算差余
            count += n // (i * 10) * i   ###计算阶梯数
            if k > i * 2 - 1:
                count += i
            elif k < i:
                count += 0
            elif i <= k <= i * 2 - 1:
                count += k - i + 1

            i = i // 10
        return count

もちろん、暴力的な方法があります:

class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        ans = 0
        for i in range(1,n+1):
            ans += str(i).count('1')
        return ans

公開された160元の記事 ウォン称賛30 ビュー70000 +

おすすめ

転載: blog.csdn.net/yixieling4397/article/details/104976134