题目:https://www.nowcoder.com/practice/bd7f978302044eee894445e244c7eee6?tpId=13&tqId=11184&tPage=2&rp=2&ru=%2Fta%2Fcoding-interviews&qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking
原理是:依次计算每个位置(个位、十位、百位…)上k出现的次数。
分三种情况:当前位的数字与k比较:大于、等于和小于。
以n=32014,k=1为例:
变量的意义写在前面:cur表示当前的位置的数字,before表示当前位置前面的数字,after表示当前位置后面的数字,例如:13234,假设当前位是2,后面的数就是34,前面的数是13;再例如:1,当前位是1,before为0,after为0。
第一步:首先计算个位上数字1出现的次数,0到32014中,个位上出现1的数为1,11,21,31,41,…,91,101,…,201,…32001,(前面有3201个)32011。(一共有3202个区间,区间长度为1,注意:是3202不是3201),总共有3201*1+1个数。
此时cur=4,k=1<4,before = 3201,after = 0。count += (3201+1)*1;
第二步:计算十位上数字1出现的次数,0到32014中,十位上出现1的数为10-19,110-119,210-219,310-319,410-419,…910-919,1010-1019,1110-1119,…31810-31819,31910-31919,外加5个32010,32011,32012,32013,32014;每个区间是十个数,每个数字的十位都是1,一共有320个区间,外加5个数,一共有320*10+4+1.
此时cur=1,cur = k;before = 320,after = 4。count += 320*10+4+1=before*10+after+1;
第三步:计算百位上数字1出现的次数,0到32014中,百位上出现1的数为100-199,1100-1199,2100-2199,…,30100-30199,31100-31199,每个区间有一百个数。每个数字的百位都是1,一共有32个区间,一共有32*100个。 第四部:…
此时cur=0,cur
以上,前三步分别对应的情况是cur大于、等于和小于k的情况,后面的依次类推。每一步中含有数字1的个数依次为:3202,3205,3200,4000,10000,总的个数为23607。
下面是完整代码,相信看了上面的解释,代码会很清晰:import java.util.Scanner;
public class digitCounts
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int n =sc.nextInt();
int k =sc.nextInt();
System.out.println(countDigitOne(n,k));
}
static int countDigitOne(int n, int k) {
int current = 0;//当前位。eg:对于数字13234,假设当前位是2,前面before的数是13,后面after的数就是34
int before = 0;//比当前位更高的数
int after = 0;//比当前位低的数
int index = 1, n_count = 0;
if (n == 0 && k == 0) {
return 1;
}
while (n / index != 0) {
if (k == 0 && n / (index * 10) == 0) {//最高位不能为0
break;
}
current = (n / index) % 10;
before = n / (index * 10);
after = n - n / index * index;//注意:此处是取出当前位的后面的数。
if (current > k) {
n_count = n_count + (before + 1) * index;
} else if (current < k) {
n_count = n_count + before * index;
} else {
n_count = n_count + before * index + after + 1;
}
index *= 10;
}
return n_count;
}
}