【问题】
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
【分析】
以21345为例,最高位为2,最高为1出现的次数为10^4,考虑其非最高为设其中一位为1,其余位1出现的次数位2*4*10^3
去掉最高位,剩余为1345,最高位为1,则最高位为1的情况有1346种情况,考虑其非最高为设其中一位为1,其余位1出现的次数位1* 3*10^2
依次递归下去,直到只剩下一位数
【解决】
① 将数字先转为字符串进行操作
public class Solution {
public static int NumberOf1Between1AndN_Solution(int n) {
if (n <= 0) return 0;
String num = n + "";
return dfs(num);
}
public static int dfs(String num){//i表示当前遍历到第几位
if (num == null || num.length() == 0){
return 0;
}
int len = num.length();
if (len == 1 && num.charAt(0) - '0' == 0){
return 0;
}
if (len == 1 && num.charAt(0) >= 1){
return 1;
}
int firCount = 0;
int otherCount = 0;
int recurCount = 0;
if (num.charAt(0) - '0' > 1){
firCount = (int) Math.pow(10,len - 1);
}
if (num.charAt(0) - '0' == 1){
firCount = Integer.valueOf(num.substring(1)) + 1;
}
otherCount = (num.charAt(0) - '0') * (len - 1) * (int)Math.pow(10,len - 2);
recurCount = dfs(num.substring(1));
return firCount + otherCount + recurCount;
}
}
② 直接计算
public class Solution {
public static int NumberOf1Between1AndN_Solution(int n) {
if (n <= 0) return 0;
return dfs(n);
}
public static int dfs(int num){//i表示当前遍历到第几位
if (num == 0) return 0;
if (num >= 1 && num <= 9) return 1;
int tmp = num;
int div = 1;
int len = 1;
while(tmp >= 10){
len ++;
tmp /= 10;
div *= 10;
}
int firNum = num / div;
int firCount = 0;
int otherCount = 0;
int recurCount = 0;
if (div != 0){
num %= div;
}
div /= 10;
if (firNum == 1){
firCount = num + 1;
}
if (firNum != 1){
firCount = (int) Math.pow(10,len - 1);
}
otherCount = (firNum) * (len - 1) * (int)Math.pow(10,len - 2);
if (len > 1 && num != 0) recurCount = dfs(num);
return firCount + otherCount + recurCount;
}
}