There is a question in both <beauty of programming> and <offoffer>, that is, the number of times 1 appears in an integer from 1 to n.
Both of these two books provide two algorithms. I think the algorithms in <the beauty of programming> are superior. The two algorithms are implemented as follows.
Method 1:
An intuitive method is to traverse every integer from 1 to n and use a sub-function to find the number of 1 contained in an integer, then, the number of times that All integers contain 1 is added to get the final result.
C code implementation:
#include <stdio.h>unsigned int totalnumberofone(unsigned int n);unsigned int numberofone(unsigned int n);int main(){ printf("%d",totalnumberofone(12)); return 0;}unsigned int totalnumberofone(unsigned int n){ unsigned int count=0; while(n>0) { count+=numberofone(n--); } return count;}unsigned int numberofone(unsigned int n){ unsigned int count=0; while(n!=0) { if(n%10==1) { ++count; } n=n/10; } return count;}
Method 2:
The time consumed by using method 1 in N is small, but if n is large, the time consumed by using the above method is large, the time complexity should be in the linear logarithm level. Can we come up with a faster approach? Or does our method have to be related to the size of N, but only the number of digits of n?
We only need a simple analysis to know that the number of occurrences of 1 can only appear on different carry numbers of N integers, from the highest bit to the lowest Bit. We only need to analyze the number of occurrences of 1 on each bit, and then add all the occurrences to get the number of occurrences of the final 1, the time complexity of this algorithm is only related to the number of digits N, that is, it belongs to the logarithm level.
C implementation:
unsigned int totalnumofone(unsigned int n){ unsigned int count=0; unsigned int highnum,lownum,curnum; unsigned int factor=1; while(n/factor!=0) { highnum=n/(factor*10); curnum=(n/factor)%10; lownum=n-(n/factor)*factor; switch(curnum) { case 0: count+=highnum*factor; break; case 1: count+=highnum*factor+lownum+1; break; default: count+=(highnum+1)*factor; } factor*=10; } return count;}
The factor value in the above program is the current carry. 1 indicates a single digit, 10 indicates ten digits, and 100 indicates a hundred digits ....... curnum indicates the number in the current bit. highnum and lownum indicate the number before the current BIT and the number after the current bit respectively. If you do not understand, you can refer to the programming beauty 2.4.