今天上午上班由于没什么事做,就看看书,发现一个算法问题,开始看感觉貌似很简单,但是越想越有意思。
1,题目描述:
给定一个十进制的正整数N,写下从1开始到N所有出现“1”的个数。
例如:
N = 2 ,写下 1 ,2 。出现了一个1;
N = 12,写下1,2,3,4,5,6,7,8,9,10,11,12.这样1的个数是5;
问题是:
1,写一个函数f(N),返回1到N之间出现的1的个数,比如f(12) = 5.
2,在32位证书范围内,满足条件“f(N) = N”的最大的N是多少?
一开始我看到这个问题,第一反应就是递归,感觉只要解决两个问题就可以了,一是算出N含有的1的个数,再根据f(N-1)就能得到f(N)的值。其中f(1) = 1 ;这是一个最简单的递归方法。写出的代码如下:
public class Jeho1 {
public static int count1(int n){
if(n == 1 ) return 1;
else return count1(n-1)+Count1InOne(n);
}
public static int Count1InOne(int m){
int count = 0 ;
String temp = new Integer(m).toString();
for(int i = 0 ; i < temp.length() ; i ++){
if(temp.charAt(i) == '1') count++;
}
return count;
}
/**
* @param args
*/
public static void main(String[] args) {
// for(int i = 1 ; i <= 99 ; i++){
// if(i == count1(i))
// System.out.println(i);
// }
System.out.println(count1(33));
}
}
刚开始我输入几个比较小点的数,发现算的都很正常,但是到了10k的时候就不行了,一看傻13了,栈溢出了。。。确实,这样递归看样子是不可能实现大数据计算的。没办法,只有继续看书寻求更好的方法。承认自己数学没有学好,看到这样的东西都不会望数据本身想,而总是想利用那些最基本的算法来实现。
书上的算法写的好复杂,简单来讲就是先从数字本来来找规律,数字的个位十位百位分开来看。由于被pdf加密,不能复制,所以自己就不太好来讲了,貌似可以上传附件,大家可以自己打开看看,这个是我按照它算法描述写的,果然计算结果就是不一样。代码献上先:
public class Jeho {
public static int count1(int n){
int count = 0 ;
int facror = 1;
int lowerNum = 0;
int currNum = 0 ;
int higherNum = 0;
while(n/facror != 0){
lowerNum = n - (n / facror) * facror;
currNum = (n / facror) % 10;
higherNum = n / (facror * 10);
switch(currNum){
case 0:
count += higherNum * facror;
break;
case 1:
count += higherNum * facror + lowerNum +1;
break;
default:
count += (higherNum + 1) * facror;
break;
}
facror *= 10;
}
return count;
}
/**
* @param args
*/
public static void main(String[] args) {
int count = 0 ;
System.out.println(Integer.MAX_VALUE);
// System.out.println(count1(100000000));
for(int i = 1 ; i < 10000000 ; i++){
if(i == count1(i)){
count++;
}
}
System.out.println(count);
}
测试了下,输出一个结果超快,哎,自己脑子还是很不够用啊,得多多学习。
1,题目描述:
给定一个十进制的正整数N,写下从1开始到N所有出现“1”的个数。
例如:
N = 2 ,写下 1 ,2 。出现了一个1;
N = 12,写下1,2,3,4,5,6,7,8,9,10,11,12.这样1的个数是5;
问题是:
1,写一个函数f(N),返回1到N之间出现的1的个数,比如f(12) = 5.
2,在32位证书范围内,满足条件“f(N) = N”的最大的N是多少?
一开始我看到这个问题,第一反应就是递归,感觉只要解决两个问题就可以了,一是算出N含有的1的个数,再根据f(N-1)就能得到f(N)的值。其中f(1) = 1 ;这是一个最简单的递归方法。写出的代码如下:
public class Jeho1 {
public static int count1(int n){
if(n == 1 ) return 1;
else return count1(n-1)+Count1InOne(n);
}
public static int Count1InOne(int m){
int count = 0 ;
String temp = new Integer(m).toString();
for(int i = 0 ; i < temp.length() ; i ++){
if(temp.charAt(i) == '1') count++;
}
return count;
}
/**
* @param args
*/
public static void main(String[] args) {
// for(int i = 1 ; i <= 99 ; i++){
// if(i == count1(i))
// System.out.println(i);
// }
System.out.println(count1(33));
}
}
刚开始我输入几个比较小点的数,发现算的都很正常,但是到了10k的时候就不行了,一看傻13了,栈溢出了。。。确实,这样递归看样子是不可能实现大数据计算的。没办法,只有继续看书寻求更好的方法。承认自己数学没有学好,看到这样的东西都不会望数据本身想,而总是想利用那些最基本的算法来实现。
书上的算法写的好复杂,简单来讲就是先从数字本来来找规律,数字的个位十位百位分开来看。由于被pdf加密,不能复制,所以自己就不太好来讲了,貌似可以上传附件,大家可以自己打开看看,这个是我按照它算法描述写的,果然计算结果就是不一样。代码献上先:
public class Jeho {
public static int count1(int n){
int count = 0 ;
int facror = 1;
int lowerNum = 0;
int currNum = 0 ;
int higherNum = 0;
while(n/facror != 0){
lowerNum = n - (n / facror) * facror;
currNum = (n / facror) % 10;
higherNum = n / (facror * 10);
switch(currNum){
case 0:
count += higherNum * facror;
break;
case 1:
count += higherNum * facror + lowerNum +1;
break;
default:
count += (higherNum + 1) * facror;
break;
}
facror *= 10;
}
return count;
}
/**
* @param args
*/
public static void main(String[] args) {
int count = 0 ;
System.out.println(Integer.MAX_VALUE);
// System.out.println(count1(100000000));
for(int i = 1 ; i < 10000000 ; i++){
if(i == count1(i)){
count++;
}
}
System.out.println(count);
}
测试了下,输出一个结果超快,哎,自己脑子还是很不够用啊,得多多学习。