public static int getLength2(int n){
int totalLength = 0;
for (int i = 1; i <= n; ++i){
int p = i;
int c = 1; // 求p的总位数
while (p >= 10){
c++;
p /= 10;
}
totalLength += c;
}
return totalLength;
}
分析:老师方法是正序累加循环计算,每次加一,计算位数相加,逐个计算时间太久。
思路:将逐个简化变成规律性增加,发现1-9是1,10-99是2,100-999是3...且一位数的数量为9,两位数的数量为90,三位数的数量为900..,则可按照9 90 900...与对应位数相乘再累加。
过程:
1.尝试从个位开始往上匹配,判断该数字位数,按位数依次累加位数和数量乘积。
2.将老师的for循环的循环条件改为判断几位数,即是否比9 99 999...大,如大于则直接将之前的按位数依次累加位数和数量乘积。然后位数递增,数量十倍递增,数字减去之前的位数数量,再进行判断。
int length = 0;
int a=9;
int c=1;
for(;num>a;num-=a){
length+=c*a;
c++;
a*=10;
}
length+=c*num;
3.报错,因为num必须在a(数量)增大前进行计算。
for(;a<num;a*=10){
length+=c*a;
c++;
num-=a;
}
4.运行正常,对代码检查后发现for可变化为while,结束条件放在最后。
代码:
package 算法.思考;
import java.util.Scanner;
public class 优化 {
//长度:1-9是1,10-99是2,100-999是3...如12长度为1*9+3*3=15
public static void main(String[] args) {
System.out.println("输入:");
Scanner sc =new Scanner(System.in);
int in=sc.nextInt();
long starttime = System.currentTimeMillis(); // 开始时间
System.out.println("长度:"+getLength(in));
long endtime = System.currentTimeMillis(); // 结束时间
System.out.println("执行用时:"+(endtime-starttime)+"ms");
}
public static int getLength(int num) {
int length = 0;
int a=9;//数量
int c=1;//位数
while(a<num){
length+=c*a;
c++;//位数增加
num-=a;//去除上一位数的数量
a*=10;//倍数增长的数量
}
length+=c*num;
return length;
}
}