題目:輸入一個整數(shù)n皮假,求從1到n這n個整數(shù)的十進(jìn)制表示中1出現(xiàn)的次數(shù)转锈。例如輸入12胧弛,從1到12這些整數(shù)中包含1的數(shù)字有1尤误,10,11和12结缚,1一共出現(xiàn)了5次.
核心思路:
根據(jù)設(shè)定的整數(shù)位置损晤,對n進(jìn)行分割,分為兩部分掺冠,高位n/i沉馆,低位n%i
當(dāng)i表示百位码党,且百位對應(yīng)的數(shù)>=2,如n=31456,i=100德崭,則a=314,b=56,此時百位為1的次數(shù)有a/10+1=32(最高兩位0~31)揖盘,每一次都包含100個連續(xù)的點(diǎn)眉厨,即共有(a%10+1)100個點(diǎn)的百位為1
當(dāng)i表示百位,且百位對應(yīng)的數(shù)為1兽狭,如n=31156,i=100憾股,則a=311,b=56鹿蜀,此時百位對應(yīng)的就是1,則共有a%10(最高兩位0-30)次是包含100個連續(xù)點(diǎn)服球,當(dāng)最高兩位為31(即a=311)茴恰,本次只對應(yīng)局部點(diǎn)00~56,共b+1次斩熊,所有點(diǎn)加起來共有(a%10100)+(b+1)往枣,這些點(diǎn)百位對應(yīng)為1
當(dāng)i表示百位,且百位對應(yīng)的數(shù)為0,如n=31056,i=100粉渠,則a=310,b=56分冈,此時百位為1的次數(shù)有a/10=31(最高兩位0~30)
綜合以上三種情況,當(dāng)百位對應(yīng)0或>=2時霸株,有(a+8)/10次包含所有100個點(diǎn)雕沉,還有當(dāng)百位為1(a%10==1),需要增加局部點(diǎn)b+1
之所以補(bǔ)8去件,是因?yàn)楫?dāng)百位為0坡椒,則a/10==(a+8)/10,當(dāng)百位>=2尤溜,補(bǔ)8會產(chǎn)生進(jìn)位位肠牲,效果等同于(a/10+1).
代碼:
<pre><code>`
func countOfNumber(num:Int) -> Int {
var index:Int = 1
var count:Int = 0
while index <= num {
let high:Int = index/10
let low:Int = index%10
let remain = (high%10 == 1) ? (low+1) : 0
count = count + (high+8)/10 * index + remain
index *= 10
}
return count
}`</code></pre>
測試:
<pre><code>`var maxNumber = 2000
var maxCount = maxSum.countOfNumber(num: maxNumber)
print("第二種方式----(maxCount)")`</code></pre>