【劍指offer】整數中1出現的次數
- 題目描述:
親們!!我們的外國友人YZ這幾天總是睡不好,初中奧數裡有一個題目一直困擾著他,特此他向JOBDU發來求助信,希望親們能幫幫他。問題是:求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數。
- 輸入:
輸入有多組資料,每組測試資料為一行。
每一行有兩個整數a,b(0<=a,b<=1,000,000,000)。
- 輸出:
對應每個測試案例,輸出a和b之間1出現的次數。
- 樣例輸入:
0 5 1 13 21 55 31 99
- 樣例輸出:
1 6 4 7
最簡單的方法,分別求從1到n之間每個數中的1的個數,由於整數n的位數為O(logn),我們要判斷一個數有多少個1,需要判斷其每一位是否為1,這樣一個數就需要判斷O(logn)次,而總共有n個數需要求,那麼該方法的時間複雜度為O(nlogn)。在九度OJ上用該方法寫的程式碼測試,會超時。
劍指offer上給了一種遞迴的思路,能將時間複雜度降到O(logn),總感覺這個思路有點偏,而且很難想到,我沒仔細看。我的想法是各位分開統計,而且看到何海濤部落格下面很多人留言,也用了這樣的方法,就看了下詳細的思路,並自己推導了下公式,寫出了程式碼,感覺這種方法還是很nice的,直觀易懂,而且程式碼簡潔,時間複雜度同為O(logn)。
這種方法的思路大概是這樣的(懶得動手打了,直接copy):
按每一位來考慮,
1)此位大於1,這一位上1的個數有 ([n / 10^(b+1) ] + 1) * 10^b
2)此位等於0,為 ([n / 10^(b+1) ] ) * 10^b
3)此位等於1,在0的基礎上加上n mod 10^b + 1
舉個例子:
30143: 由於3>1,則個位上出現1的次數為(3014+1)*1 由於4>1,則十位上出現1的次數為(301+1)*10 由於1=1,則百位上出現1次數為(30+0)*100+(43+1) 由於0<1,則千位上出現1次數為(3+0)*1000 注:以百位為例,百位出現1為100~199,*100的意思為單步出現了100~199,100次,*30是因為出現了30次100~199,+(43+1)是因為左後一次301**不完整導致。 如果還不懂,自己拿紙和筆大致寫下,找下規律,就能推匯出來了! 兩外,需要注意一點:由於測試系統要求的輸入資料最大為1,000,000,000,因此用int會溢位,要用long long,另外比較坑跌的一點是a可能比b大,居然都沒有說明,有點坑了。#include<stdio.h>
/*
分別統計num各位上1出現的次數,
相加得到1出現的總次數
*/
long long CountNum1(long long num)
{
if(num <= 0)
return 0;
long long count = 0; //統計1出現的次數
long long current; //當前位
long long base = 1; //當前位的基
long long remain = 0; //當前位為1時,後面位剩餘的數(即不完整的部分)中1出現的次數
while(num)
{
current = num%10;
num = num/10;
if(current > 1)
count += (num+1)*base;
else if(current == 1)
count += num*base + (remain+1);
else
count += num*base;
//下一位要用到的基和剩餘不完整部分值
remain += current*base;
base *= 10;
}
return count;
}
int main()
{
long long a,b;
//a,b的大小不定
while(scanf("%lld %lld",&a,&b) != EOF)
{
long long result;
if(a > b)
result = CountNum1(a) - CountNum1(b-1);
else
result = CountNum1(b) - CountNum1(a-1);
printf("%lld\n",result);
}
return 0;
}
/**************************************************************
Problem: 1373
User: mmc_maodun
Language: C
Result: Accepted
Time:0 ms
Memory:912 kb
****************************************************************/
相關推薦
【劍指offer】整數中1出現的次數(從1到n整數中1出現的次數)
題目描述 求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數(從1
【劍指offer】整數中1出現的次數
題目描述:親們!!我們的外國友人YZ這幾天總是睡不好,初中奧數裡有一個題目一直困擾著他,特此他向JOBDU發來求助信,希望親們能幫幫他。問題是:求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、1
【劍指offer】二進位制中1的個數(java)
問題描述:輸入一個二進位制數,我們記為num,計算出num中有幾個1,結果用count儲存 思路分析:如二進位制數11011,將其減1,得11010,再與原來的數做與運算 11011&11010,得11010,此二進位制數相比原二進位制數,數中的1少了一個。重複此過程,直至該數變為0
【劍指Offer】二進位制中1的個數
題目描述 輸入一個整數,輸出該數二進位制表示中1的個數。其中負數用補碼錶示。 補碼 解題前,我們先來了解一下補碼。在計算機系統中,數值都是用補碼來表示和儲存的。 而原碼就是數值的二進位制數表示,最高位1表示負數。 以32位數值舉例 1的原碼就是 -1的原碼就是 正數的補碼等於原碼 負數的補碼等於其原碼
劍指offer:整數中1出現的次數
題目描述 求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區
【劍指offer】陣列中只出現一次的數字
remove:刪除特定元素第一次出現的時候,返回的是刪除後的陣列 del:刪除指定索引的元素 del a[2],返回的是刪除後的陣列 pop:刪除指定索引的元素,返回的是刪除的元素 有一個問題就是我不知道判斷not in list 的時候O(n)的複雜度會不會影響 執
[劍指offer] 31. 整數中1出現的次數(從1到n整數中1出現的次數)
題目描述 求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數(從1
劍指offer:整數中1出現的次數(python)
求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數。
劍指offer——31.整數中1出現的次數
題目描述 求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出
劍指offer:整數中1出現的次數(從1到n整數中1出現的次數)(Python)
題目描述 求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出
劍指offer--32.整數中1出現的次數(從1到n整數中1出現的次數)
public return between acm span class turn style ++ 暴力挨個數 ---------------------------------------------------------------------- 時間限制:1秒
【劍指offer】43、1~n整數中1出現的次數
ase 表示 eight pre pub 題目 我們 return 1出現的次數 題目 輸入一個整數,求1~n的整數十進制表示中1出現的次數。如12,有1,10,11,12,總共出現了5次。 思路 註意不是統計出現1的數字的多少,而是統計1出現了幾次。 我們按位來分析 個位
【劍指offer】無聊的1+2+...+n
乘除 detail lin targe while http off 技術分享 i++ 轉載請註明出處:http://blog.csdn.net/ns_code/article/details/27964027題目描寫敘述:求1+2+3+...+n,要求不能使用乘除法、f
【劍指offer】圓圈中最後剩下的數字,C++實現
一行 AC 個人 ron namespace itl i++ float color 原創博文,轉載請註明出處! # 題目 # 思路 本題即為典型的約瑟夫問題,通過遞推公式解決。 第一行表示每個人的下標,現在要從11個人中刪除報數為3的人,從圖
【劍指offer】序列中的某一位數字
題目描述 數字以01234567891011121314…的格式序列化到一個字元序列中,在這個序列中,從0開始數,第5位是5,第13位是1,第19位是4,等等,請寫一個函式,求任意第n位對應的數字。 求出每一位對應的數字總和,然後判斷。注意邊界條件不好處理時,可以採用while true
【劍指offer】陣列中的逆序對(校正書上錯誤)【歸併排序】
題目描述 在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007 題目保證輸入的陣列中沒有的相同的數字 資料範圍:
【劍指Offer】陣列中重複的數字
題目連結 題目描述 在一個長度為n的數組裡的所有數字都在0到n-1的範圍內。 陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意一個重複的數字。 例如,如
【劍指offer】矩陣中的路徑(回溯法)
# -*- coding:utf-8 -*- class Solution: def hasPathCore(self, matrix, rows, cols, row, col, path,
【劍指offer】陣列中出現次數超過陣列長度一半的數字(三種解法)
題目描述 陣列中有一個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入一個長度為9的陣列{1,2,3,2,2,2,5,4,2}。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。如果不存在則輸出0。 如果使用時間複雜度為O(n),可以構建
【劍指Offer】第一個只出現一次的字元
題目連結 題目描述 在一個字串(0<=字串長度<=10000,全部由字母組成)中找到第一個只出現一次的字元,並返回它的位置, 如果沒有則返回 -1(需要區分大小寫). 分析:簡單計數並