题目
输入一个整数n,求1-n这n个整数的十进制表示中1出现的次数。
例如
输入12
这些整数中包含1的整数有1,10,11,12。1一共出现了5次。
思路
思路一
暴力解法。遍历从1到n的n个整数,并且每个整数挨个检查每一位是否是1.时间复杂度太高。
思路二
使用递归的思想。
例如输入的整数为21345.
把其分为1-1345和1346-21345两部分求解。
先看1346-21345这部分。
1在万位出现的时候为10000-19999共10000次。
1在低于万位的出现次数为2*4*(10^3) = 8000次。
所以在1346-21345这部分1出现的次数为18000次。
1-1345这部分用递归求解。
代码
思路二
题目
输入一个整数n,求1-n这n个整数的十进制表示中1出现的次数。
例如
输入12
这些整数中包含1的整数有1,10,11,12。1一共出现了5次。
思路
思路一
暴力解法。遍历从1到n的n个整数,并且每个整数挨个检查每一位是否是1.时间复杂度太高。
思路二
使用递归的思想。
例如输入的整数为21345.
把其分为1-1345和1346-21345两部分求解。
先看1346-21345这部分。
1在万位出现的时候为10000-19999共10000次。
1在低于万位的出现次数为2*4*(10^3) = 8000次。
所以在1346-21345这部分1出现的次数为18000次。
1-1345这部分用递归求解。
代码
思路二
public static int numberOf1(int n){
String str = String.valueOf(n);
int first = str.charAt(0) - '0';
int length = str.length();
if(length == 1 && first == 0)return 0;
if(length == 1 && first > 0)return 1;
int numFirstDigit = 0;
if(first > 1){
numFirstDigit = powerBase10(length - 1);
}
else if(first == 1){
numFirstDigit = Integer.valueOf(str) - powerBase10(length - 1) + 1;
}
int numOtherDigit = first * (length - 1) * powerBase10(length - 2);
int numRecursive = numberOf1(Integer.valueOf(str) - first * powerBase10(length - 1));
return numFirstDigit + numOtherDigit + numRecursive;
}
public static int powerBase10(int n){
return (int)Math.pow(10,n);
}
总结
本题采用了递归的思路。需要发现去掉最高位的数到末尾的数中1出现次数的规律。
总结
本题采用了递归的思路。需要发现去掉最高位的数到末尾的数中1出现次数的规律。