《剑指offer》面试题32:从1到n整数中k出现的个数

题目:输入一个整数m,求从1到n这n个整数的十进制表示中k出现的次数。例如输入一个12,从1到12这些整数中包含1的数字有1,10,11和12,1一共出现了5次。

思路:分别统计k出现在个位,十位,百位,千位...的个数。

n = 2593, x = 5 为例来解释如何得到数学公式。从 1 至 2593中,数字 5 总计出现了 813 次,其中有 259次出现在个位,260次出现在十位,294次出现在百位,0次出现在千位。

  • 现在依次分析这些数据,首先是个位。从 1 至 2590 中,包含了 259 个 10,因此任意的 x 都出现了 259 次。最后剩余的三个数 2531,2592,2593,因为它们最大的个位数字 3 < x。因此不会包含任何 5. (也可以这么看, 3 < x, 则个位上可能出现的 x 的位数由更高位决定,等于更高位数字 (259) * 101-1 = 259)。
  • 然后是十位。从 1 至 2500中,包含了25个100,因此任意的 x 都出现了 25 * 10 = 250 次。剩下的数字从 2501 至 2593,它们最大的十位数是 9 > x,因此会包含全部 10 个 5。最后总计 250 + 10 = 260。(也可以这么看,9 > x,则十位上可能出现的 x 的位数由更高位决定,等于更高位数字(25 + 1) * 102-1 = 260。
  • 接下来是百位。从1至2000中,包含了2个1000,因此任意x都出现了2 * 100 = 200次。剩下的数字从2001至2593,它们最大的百位数字5 == x,这时候情况就略微复杂,它们的百位肯定是包含5的,但是不会包含全部100个。如果把百位是5的列出来,是从2500至2593,数字的个数与十位和个位数字有关,是93 + 1 = 94。最后总计 200 + 94 = 294。(也可以这么看, 5 == x,则百位上可能出现的x次数不仅受跟高位影响,还受低位影响,等于更高位数字 2 * 103-1 + (93 + 1))。
  • 最后是千位,现在已经没有更高位,因此直接看最大的千位数字 2 < x,因此不会包含任何 5 。(也可以这么看,2 < x,则千位上可能出现的x的次数仅由更高位决定,等于更高位数字 0 * 104-1 = 0)

注意:不能直接用每个数去除以10的幂计算1的个数。

public int NumBetweenKAndN(int n, int k) {
	if (n < k)
		return 0;
	if (n >= k && n <= 9)
		return 1;
	
	int i = 1;
	int res = 0;
	while (i < n) {
		int high = n / i;	// 最高位
		res += high * i / 10;
		
		int nn = n % i * 10 / i;	// 除去最高位的余数
		if (nn == k)	// 余数的最高位等于k
			res += n % i - nn * i / 10;
		if (nn > k)		// 余数的最高位大于k
			res += (i / 10);
		
		i *= 10;	// 省去pow运算
	}
	return res;
}

参考:https://www.cnblogs.com/lengender-12/p/6876897.html

猜你喜欢

转载自blog.csdn.net/qq_25024883/article/details/80337312
今日推荐