正整数中数字1的计数问题 - 简单算法(上)
正整数中数字1的计数问题(上)
原题出自Google的一道比较老的面试题:
Consider a function which, for a given whole number n, returns the number of ones required when writing out all
numbers between 0 and n.
For example, f(13)=6. Notice that f(1)=1. What is the next largest n such that f(n)=n?
本实现没有利用可能存在的数学公式,只考虑相邻两个数得变化规律,因此运行效率并不理想。如何计算单个值f(n)的快速算法,请参考我的另一篇文章。
public class OnesCount { /** * Problem: * Consider a function which, for a given whole number n, * returns the number of ones required when writing out all * numbers between 0 and n. * For example, f(13)=6. Notice that f(1)=1. * What is the next largest n such that f(n)=n? * * * Print the next i for f(i)=i; stop when we reach n and return f(n). * n: long integer */ public static long solve(long n){ //the number of digits in n int digitsCount=1; long tmp = n; while((tmp /= 10) >0) digitsCount++; int prevDigitIndex = digitsCount - 2; int leastDigitIndex = digitsCount - 1; if(prevDigitIndex<0){ //one-digit input System.out.format("n=%d=f(n)%n",0); if(n>0) System.out.format("n=%d=f(n)%n",1); int count = 0; if(n<=1){ //0 and 1 count = (int)n; }else{ count = 1; } return count; } //initialized to zero byte[] digits = new byte[digitsCount]; long totalOnesCount = 0; int nextOnesCount = 0; int k=0; //the least significant digit: from 0 to 9 for(long i=0;i<=n;i++){ int currOnesCount = nextOnesCount; if(k==0){ //x0 - > x1 digits[leastDigitIndex] = 1; nextOnesCount = currOnesCount + 1; }else if(k==1){ //x1 - > x2 digits[leastDigitIndex] = 2; nextOnesCount = currOnesCount - 1; }else if(k==9){ //x9 -> ... byte nextDigit = digits[prevDigitIndex]; //x switch(nextDigit){ case 0: //09 -> 10 digits[prevDigitIndex] = 1; digits[leastDigitIndex] = 0; nextOnesCount = currOnesCount + 1; break; case 1: //19 -> 20 digits[prevDigitIndex] = 2; digits[leastDigitIndex] = 0; nextOnesCount = currOnesCount - 1; break; case 9: //99 int tmpIndex = prevDigitIndex; digits[leastDigitIndex] = 0; digits[prevDigitIndex] = 0; while((--tmpIndex)>=0 && digits[tmpIndex]==9){ digits[tmpIndex] = 0; } if(tmpIndex>=0){ int d = (digits[tmpIndex]+=1); if(d==2){ //199 -> 200 nextOnesCount = currOnesCount - 1; }else if(d==1){ //099 -> 100 nextOnesCount = currOnesCount + 1; }else{ //399 -> 400 nextOnesCount = currOnesCount; } } break; default: //29 ~ 89 -> 30 ~ 90 digits[prevDigitIndex] += 1; digits[leastDigitIndex] = 0; nextOnesCount = currOnesCount; break; } }else{ //x2 ~ x8 -> x3 ~ x9 digits[leastDigitIndex] += 1; nextOnesCount = currOnesCount; } k = digits[leastDigitIndex]; totalOnesCount += currOnesCount; if(i==totalOnesCount){ System.out.format("n=%d=f(n)%n",i); } } return totalOnesCount; } public static void main(String[] args) { long n=1111111110; //long n=1111111110; //long n=1036; long start = System.currentTimeMillis(); long ones = OnesCount.solve(n); System.out.format("f(%d) = %d%n",n,ones); long end = System.currentTimeMillis(); double timeElapsed = (end-start)/1000.0; System.out.format("Time elapsed(sec): %.3f%n", timeElapsed); } }
测试结果(Pentium M 1.4GHz, 512M内存):
n=0=f(n)
n=1=f(n)
n=199981=f(n)
n=199982=f(n)
n=199983=f(n)
n=199984=f(n)
n=199985=f(n)
n=199986=f(n)
n=199987=f(n)
n=199988=f(n)
n=199989=f(n)
n=199990=f(n)
n=200000=f(n)
n=200001=f(n)
n=1599981=f(n)
n=1599982=f(n)
n=1599983=f(n)
n=1599984=f(n)
n=1599985=f(n)
n=1599986=f(n)
n=1599987=f(n)
n=1599988=f(n)
n=1599989=f(n)
n=1599990=f(n)
n=2600000=f(n)
n=2600001=f(n)
n=13199998=f(n)
n=35000000=f(n)
n=35000001=f(n)
n=35199981=f(n)
n=35199982=f(n)
n=35199983=f(n)
n=35199984=f(n)
n=35199985=f(n)
n=35199986=f(n)
n=35199987=f(n)
n=35199988=f(n)
n=35199989=f(n)
n=35199990=f(n)
n=35200000=f(n)
n=35200001=f(n)
n=117463825=f(n)
n=500000000=f(n)
n=500000001=f(n)
n=500199981=f(n)
n=500199982=f(n)
n=500199983=f(n)
n=500199984=f(n)
n=500199985=f(n)
n=500199986=f(n)
n=500199987=f(n)
n=500199988=f(n)
n=500199989=f(n)
n=500199990=f(n)
n=500200000=f(n)
n=500200001=f(n)
n=501599981=f(n)
n=501599982=f(n)
n=501599983=f(n)
n=501599984=f(n)
n=501599985=f(n)
n=501599986=f(n)
n=501599987=f(n)
n=501599988=f(n)
n=501599989=f(n)
n=501599990=f(n)
n=502600000=f(n)
n=502600001=f(n)
n=513199998=f(n)
n=535000000=f(n)
n=535000001=f(n)
n=535199981=f(n)
n=535199982=f(n)
n=535199983=f(n)
n=535199984=f(n)
n=535199985=f(n)
n=535199986=f(n)
n=535199987=f(n)
n=535199988=f(n)
n=535199989=f(n)
n=535199990=f(n)
n=535200000=f(n)
n=535200001=f(n)
n=1111111110=f(n)
f(1111111110) = 1111111110
Time elapsed(sec): 32.657