题目是C++版块上的,我想用java实现:
http://topic.csdn.net/u/20081102/11/1c6136bb-ad44-49e1-868b-d848816456f6.html最笨的算法(计算111111111需要78秒....):package cn.array;/**
* 计算enterNum之前正数所有1的个数,比如:1->1;10->2;11->4;12->5.......
* @author liaoyi
* @version 1.0.0
* @2008-11-3 下午03:22:10
*/
public class HasOne {
public static void main(String args[]) {
System.out.println(new HasOne().f(111111111));
}
public int f(int enterNum){
int oneNum = 1;
for(int i=enterNum;i>1;i--){
String strNum = new Integer(i).toString();
for(int j = 0;j<strNum.length();j++){
if(strNum.substring(j, j+1).equals("1"))
oneNum++;
}
}
return oneNum;
}}
大家讨论一下~
http://topic.csdn.net/u/20081102/11/1c6136bb-ad44-49e1-868b-d848816456f6.html最笨的算法(计算111111111需要78秒....):package cn.array;/**
* 计算enterNum之前正数所有1的个数,比如:1->1;10->2;11->4;12->5.......
* @author liaoyi
* @version 1.0.0
* @2008-11-3 下午03:22:10
*/
public class HasOne {
public static void main(String args[]) {
System.out.println(new HasOne().f(111111111));
}
public int f(int enterNum){
int oneNum = 1;
for(int i=enterNum;i>1;i--){
String strNum = new Integer(i).toString();
for(int j = 0;j<strNum.length();j++){
if(strNum.substring(j, j+1).equals("1"))
oneNum++;
}
}
return oneNum;
}}
大家讨论一下~
等高人ing。。
编程之美上的题目
int num[][]=new int[2][454193];
num[0][head]=1;
num[1][head]=1;
for(int i=11;i<=1111111;i++)
{
int k=has1(i);
if(k>0)
{
head++;
num[0][head]=num[0][head-1]+k;
num[1][head]=i;
}
}
int i;
for(i=0;i<=head;i++)
if(num[1][i]>111111111)break;
cout<<num[0][i-1]<<endl;
}
int has1(int a)
{
int sum=0;
while(a/10)
{
if(a%10==1)sum++;
a=a/10;
}
return sum;
}
你一万多的电脑 大部分都是花在了显示器和显卡上面了 纯粹做浮点运算的机器的都是多CPU的
int result = 0;
for( int i=10; i<=x*10; i=i*10) {
result += x/i*(i/10);//默认当前位数的值是0
if (x%i/(i/10)==1) {//当前位数的值是1
result += x%(i/10)+1;
}else if(x%i/(i/10)>1) {//当前位数的值大于1
result += i/10;
}
}
System.out.println(result);
}[我的算法主要是从每一位的1出现次数考虑的:如101 1在个位出现的次数是101/10*1=10 当前位数的值(x%i/(i/10)==1)即个位是1所以 次数=10+1;同理求得十位和百位的值。这个我还没有验证过百位以上的不知道对不对,有不对的还请大家指正
int x =11111;
int result = 0;
int testresult = 0;
for( int i=10; i<=x*10; i=i*10) {
result += x/i*(i/10);//默认当前位数是0
if (x%i/(i/10)==1) {//当前位数是1
result += x%(i/10)+1;
}else if(x%i/(i/10)>1) {//当前位数大于1
result += i/10;
}
}
for (int i=0; i<=x; i++) {
String s = i+"";
String s1 = s.replaceAll("1", "");
testresult +=s.length()-s1.length();
}
System.out.println(result);
System.out.println(testresult);
}
写了个测试的方法 发现刚刚的算法应该是没有错的
int result = 0;
int testresult = 0;
long start = System.currentTimeMillis();
for( int i=10; i<=x*10; i=i*10) {
result += x/i*(i/10);//默认当前位数是0
if (x%i/(i/10)==1) {//当前位数是1
result += x%(i/10)+1;
}else if(x%i/(i/10)>1) {//当前位数大于1
result += i/10;
}
}
long end = System.currentTimeMillis();
long teststart = System.currentTimeMillis();
for (int i=0; i<=x; i++) {
String s = i+"";
String s1 = s.replaceAll("1", "");
testresult +=s.length()-s1.length();
}
long testend = System.currentTimeMillis();
System.out.println("花费时间:"+(end-start));
System.out.println(result);
System.out.println("test花费时间:"+(testend-teststart));
System.out.println(testresult);测试结果:花费时间:0
8888896
test花费时间:20265
8888896
import javax.swing.*;
public class phenixHasOne{
public static void main(String[]args){
String strNumber=JOptionPane.showInputDialog("please input the number ");
//int number=Integer.parseInt(strNumber);
int oneNumbers=0;
for(int i=strNumber.length()-1,j=0;i>=0;i--,j++)
{
String strbefore=strNumber.substring(0,i);
String strlast=strNumber.substring(i+1,strNumber.length());
String strcurrentNumber=strNumber.substring(i,i+1);
//只有一位的时候
if(strbefore.equals("")&&strlast.equals("")){
oneNumbers+=OneNumbers(0,0,Integer.parseInt(strcurrentNumber),(int)Math.pow(10.0,(double)j));
break;
}
//当是第一次=的时候
if(i==strNumber.length()-1)
{
strlast="";
System.out.println("前边数字:"+strbefore);
System.out.println("后边数字"+strlast);
System.out.println("当前数字"+strcurrentNumber);
oneNumbers+=OneNumbers(Integer.parseInt(strbefore),0,Integer.parseInt(strcurrentNumber),(int)Math.pow(10.0,(double)j));
continue;
}
//最后一次的时候
if(i==0)
{
strbefore="";
System.out.println("前边数字:"+strbefore);
System.out.println("后边数字"+strlast);
System.out.println("当前数字"+strcurrentNumber);
oneNumbers+=OneNumbers(0,Integer.parseInt(strlast),Integer.parseInt(strcurrentNumber),(int)Math.pow(10.0,(double)j));
continue;
}
System.out.println("前边数字:"+strbefore);
System.out.println("后边数字"+strlast);
System.out.println("当前数字"+strcurrentNumber);
oneNumbers+=OneNumbers(Integer.parseInt(strbefore),Integer.parseInt(strlast),Integer.parseInt(strcurrentNumber),(int)Math.pow(10.0,(double)j));
System.out.println(".......................................");
}
System.out.println("total numbers of one is "+oneNumbers);}
public static int OneNumbers(int before,int last,int currentNumber,int metric){
int number=0;
if(currentNumber>1)
{
number=(before+1)*metric;
}
if(currentNumber==1)
{
//说明是个位
if(metric==1){
number=before+1;
}
else{
number=(before)*metric+(last+1);
}
}
if(currentNumber==0)
{
number=before*metric;
}
return number;} }//看看这个行不?
package net.csdn.community;public class Test {
public static int ccccc(int num, int tens, int a) {
if (tens == 0) return 0;
int ak = num / tens;
if (ak > a) {
return tens + ccccc(num % tens, tens / 10, a) + ak * ccccc(tens - 1, tens / 10, a);
}
else
if (ak == a) {
return num % tens + 1 + ak * ccccc(tens - 1, tens / 10, a) + ccccc(num % tens, tens / 10, a);
}
else {
return ccccc(num % tens, tens / 10, a) + ak * ccccc(tens - 1, tens / 10, a);
}
}
public static void main(String[] args) {
System.out.println(ccccc(200, 100, 1));
}}吃飯前看到這貼,搞到吃飯都在發呆...
一位的时候 1的个数是 1;
二位的时候 1的个数是 1+10+1;
三位的时候 1的个数是 12+100+12;
...
i位的时候 1的个数是 i*10的i-1次方+2倍的i-1位的和,其中条件i要大于一;这样可以用递归来求解
/**
* 思想:遍历由1到n的这个数组,分析每一个数
* 让这个数除以它10的位数-1次方,如123除以100会得到1,
* 然后取余得到23,再除以10,得到2,
* 取余得到3,再除以1得到3,取余得0,结束
* 效率是O(n)乘以n的位数
* @author 星情
*
*/
public class Test4 {
public static void main(String args[]) {
int num = 11111111;
long i1 = System.currentTimeMillis();
System.out.println(num + "总共有" + new Test4().oneNums(num));
long i2 = System.currentTimeMillis();
System.out.println("运行时间:" + (i2 - i1) + "毫秒");
}
/**
* 计算总共出现1的次数
* @param num
* @return
*/
private int oneNums(int num) {
//出现1的次数
int oneCount = 0;
for (int i = 1; i <= num; i++) {
//遍历每个数,oneNum返回该数含有1的个数
oneCount += oneNum(i);
}
return oneCount;
} /**
* 单个数字里面出现1的次数
* @param i 要计算的数
* @return 该数字中出现1的次数,如121出现1的次数2
*/
private int oneNum(int i) {
//在这个数中,含有1的个数
int count = 0;
//等于参数i的值,目的是计算出i是几位数,如i是52364,得出i的值10000
int num = i;
//计算出num
int bit = 1;
while (num > 9) {
bit = bit * 10;
num = num / 10;
}
/*
* 此时,bit是10的i位数-1次方,每次循环会得到最高位的值,循环完成后
* 会得到该数具有1的个数,如i的值是1321
* 第一次循环i/bit(1321/1000)等于1,count++(此时count=1),然后i%bit,bit降一位
* 第二次循环321/100等于3,然后ii%bit,bit降一位
* 第三次循环21/10等于2,然后ii%bit,bit降一位
* 第四次循环1/1等于1,count++(此时count=2)然后ii%bit,bit降一位
* 第五次循环时,因为i取i%bit==0,所以循环结束
*/
while (i != 0) {
if (i / bit == 1)
count++;
i = i % bit;
bit = bit / 10;
}
return count;
}
}
这是我写的算法,没有用字符串,不过效率好像也不是很高,等待改善
我的算法复杂度只是n的位数次循环 应该是最低的 下面的转成string的原始算法只是比较,谁知这样一来大家就看不出来了,郁闷中。。,
int result = 0;
int testresult = 0;
long start = System.currentTimeMillis();//纪录循环开始时间
for( int i=10; i<=x*10; i=i*10) {
result += x/i*(i/10);//默认当前位数是0
if (x%i/(i/10)==1) {//当前位数是1
result += x%(i/10)+1;
}else if(x%i/(i/10)>1) {//当前位数大于1
result += i/10;
}
}
long end = System.currentTimeMillis();//结束时间
System.out.println("花费时间:"+(end-start));
System.out.println(result);
---测试结果
花费时间:0
100000008
我这里加时间主要是为了和long teststart = System.currentTimeMillis();
for (int i=0; i<=x; i++) {
String s = i+"";
String s1 = s.replaceAll("1", "");
testresult +=s.length()-s1.length();
}
long testend = System.currentTimeMillis();
这个较慢的算法作比较,所以时间精度很低的,时间精度高的我也不会, 呵呵 还望高手指点下 求运行时间的方法
public class Test {
public static void main(String []args){
System.out.println(new Test().countOne(12));
}
public int countOne(int i){
int k=i;
int sum=0;//1的个数
int n=0;
if(i>=1&&i<=9)return 1;
do{
int j=i%10;
if(n==0){
if(j!=0)
sum+=1;
}else{
if(j==1){
int l=(int)(k%(Math.pow(10, n)));
sum+=(int)(j*n*Math.pow(10, n-1)+l+1);
}else{
sum+=(int)(j*n*Math.pow(10, n-1)+Math.pow(10, n));
}
}
i/=10;
}while(k>Math.pow(10, ++n));
return sum;
}
}我测试了,可以,而且,速度也绝对不慢。具体细节见
http://blog.csdn.net/wenlz123/archive/2008/11/05/3226234.aspx
if(base==1){
return num>=1?1:0;
}
int n = num/base;
int tail = num-n*base;
int temp = 0;
switch(n){
case 0:break;
case 1:temp = tail+1;break;
default:temp = base;
}
return temp+n*(count(base-1,base/10))+count(tail,base/10);
}
public static void main(String[] args){
long now = System.currentTimeMillis();
System.out.println(count(111111111,100000000));
now = System.currentTimeMillis()-now;
System.out.println(now);
}
public static void main(String args[]) {
System.out.println(new Factorial().f(11111111));
} public int f(int enterNum) {
int oneNum = 1;
int Index1 = 0;
int lastIndex1 = 0;
for (int i = 10; i <= enterNum; i++) {
String strNum = String.valueOf(i);
char[] cha = strNum.toCharArray();
Arrays.sort(cha);
strNum = new String(cha);
Index1 = strNum.indexOf("1");
lastIndex1 = strNum.lastIndexOf("1")+1;
if(Index1 > -1) {
oneNum += strNum.substring(Index1, lastIndex1).length();
}
}
return oneNum;
}
}
效率并不算高,但代码比较简单。
int x =111111111;
int result = 0;
long start = System.nanoTime();//纪录循环开始时间
for( int i=10; i<=x*10; i=i*10) {
result += x/i*(i/10);//默认当前位数是0
if (x%i/(i/10)==1) {//当前位数是1
result += x%(i/10)+1;
}else if(x%i/(i/10)>1) {//当前位数大于1
result += i/10;
}
}
long end = System.nanoTime();//结束时间
System.out.println("花费时间:"+(end-start)+"毫微秒");
System.out.println(result);
修改了一下测试时间的精度 System.nanoTime();这个是毫微秒级的测试结果:
花费时间:3254毫微秒
100000008
用大量除的,大量mod的基本上很慢,
用字符串的,速度差10^6倍吧
charAt方法,要比substring的效率要高,因为楼主只是想比较某一个字符。
试试if(strNum.charAt(j)=='1')...
应该会快很多。当然,支持使用 用数学计算的方法。