输出1~n中数字k(k为0到9中任意数字)出现的次数(java实现)

题目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<k,before = 32,after = 14,count +=32*100 = before*100。

第四部:…
以上,前三步分别对应的情况是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;

	}
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值