给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有1的个数

这个是《编程之美》上的一个题目,题目如题:

给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有1的个数。

书上给出了两个解法,第一个就是笨方法,挨个数呗,最后加一块。

第二个解法,有兴趣的自己看书上的分析吧,这里先把Java实现的代码贴下:

public static long F_Sum1s(long n){
		long iCount = 0;
		long iFactor = 1;
		long iLowerNum = 0;
		long iCurrNum = 0;
		long iHigherNum = 0;
		
		while(n/iFactor != 0){
			iLowerNum = n - (n/iFactor)*iFactor;
			iCurrNum = (n/iFactor)%10;
			iHigherNum=n/(iFactor*10);
			
			switch(String.valueOf(iCurrNum)){
			case "0":
				iCount += iHigherNum*iFactor;
				break;
			case "1":
				iCount += iHigherNum*iFactor+iLowerNum+1;
				break;
			default:
				iCount += (iHigherNum+1)*iFactor;
				break;
			}
			iFactor *= 10;
		}
		return iCount;
	}


之前我想到一个递推公式,想来和书上的解法本质应该差不多,现把公式和代码贴出来供大家讨论下,是否正确(自己简单试了下,12位以下的数字,和书上的结果一样,但没严格证明过)。

给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有1的个数_第1张图片

实际求的时候,先计算该数长度,然后判断Gn存在否,不存在,就求出之,最后递推求出结果,代码如下:

package algorithm;

public class Sum1s {
	
	public static long F_Sum1s(long n){ //上面已贴出}
	int[] GArr = new int[100];  //存放G的数组
	int GArrIndex = 0;
	public Sum1s(){
		GArr[0]=0; GArr[1]=0; GArr[2]=1;
		GArrIndex = 2;
	}

	public long My_Sum1s(long n){   //计算的函数
 		if(n == 0){
			return 0;
		}
		int numLength = 1;
		long tempNum = n;
		int An = 0;
		while(tempNum/10 != 0){
			numLength += 1;
			tempNum = tempNum/10;
		}
		An = (int)tempNum;
		//System.out.println("NumLength = "+numLength);
		
		if(numLength == 1){
			return 1;
		}
		
		if(numLength > GArrIndex){
			InitGArr(numLength);
		}
		
		long numLength_1_10 = 1;
		for(int i=1; i

你可能感兴趣的:(读书笔记,算法)