编程之美之1的数目

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

例如:

N=2,写下1,2。1只出现了1次。

1、写一个函数f(N),返回1到N之间,出现的“1”的个数,比如f(12)=5;

2、满足条件“f(N)=N”的最大的N是多少?

解法一:

从1遍历到N,计算每个数[1…N]上出现的1的次数。

public class Main {

	public static void main(String[] args) {
		int n = 100000000;
		System.out.println(fun(n));
	}

	private static int fun(int n) {
		int count = 0;
		for (int i = 1; i <= n; i++) {
			count += funExtra(i);
		}
		return count;
	}

	private static int funExtra(int n) {
		int count = 0;
		while (n > 0) {
			count += (n % 10 == 1) ? 1 : 0;
			n /= 10;
		}
		return count;
	}
}

解法一的时间复杂度为O(N*log2(N))。

解法二:

从个位到遍历到最高位,计算每个位上面1出现的次数,同时进行累加。

例如:

N=12013

1、在个位上为3,则“1”出现的次数与前面的4位“1201”有关,出现“1”的次数为1201+1=1202次;

2、在十位上位1,则“1”出现的次数与前面的3位“121”和后面的“3”有关,出现“1”的次数为120*10+(3+1)=1204次;

3、在百位上位0,则“1”出现的次数与前面的2位“12”和后面的“13”有关,出现“1”的次数为12*100=1200次;

4、在千位上位2,则“1”出现的次数与前面的1位“1”和后面的“13”有关,出现“1”的次数为(1+1)*1000=2000次;

4、在万位上位1,则“1”出现的次数与后面的“2013”有关,出现“1”的次数为2013+1=2014次;

一共有7620个1。

其中,要注意的是必须对每个位上出现的数字分三种情况进行讨论:

1、“0”,

2、“1”,

3、“2,3,4,5,6,7,8,9”

代码如下:

public class Main {

	public static void main(String[] args) {
		int n = 12013;
		System.out.println(fun(n));
	}

	private static int fun(int n) {

		int mCurrent = 0;
		int mUp = 0;
		int mDown = 0;
		int j = 1;
		int count = 0;
		while (n / j != 0) {
			mCurrent = n / j % 10;
			mUp = n / (10 * j);
			mDown = n - (n / j) * j;
			switch (mCurrent) {
			case 0:
				count += mUp * j;
				break;
			case 1:
				count += mUp * j + mDown + 1;
				break;
			default:
				count += (mUp + 1) * j;
				break;

			}
			j *= 10;
			System.out.println(count);
		}
		return count;
	}
}

对于满足N=f(N)的最大N是多少。

我们如下分析:

当N<=9时,1有1个;

当N<=99时,1有20个;

当N<=999时,1有300个;

可以得出公式:f(10^n-1)=n*10^(n-1)

可以发现当n>=10时,f(10^n-1)<n*10^(n-1),当n<=9时,f(10^n-1)>n*10^(n-1)。

在10^9-1<N<10^10-1之间,可能存在N=f(N)。

最后得到N=1111111110时,成立。

    原文作者:zhbing0322
    原文地址: https://blog.csdn.net/zhbing0322s/article/details/45484855
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞