面试题44-数字序列中某一位的数字

题目

数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从0开始计数,即从第0位开始)是5,第13位是1,第19位是4,等等。请写一个函数,求任意第n位对应的数字。

解题思路

方法1:

第一种思路是:从0开始枚举每个数字。每枚举一个数字的时候,求出该数字是几位(如15是2位数、9323是4位数),并把该数字的位数和前面所有数字的位数累加。如果位数之和仍然小于等于n,则继续枚举下一个数字。当累加的数位大于n时,那么第n位数字一定在这个数字里。(此处为什么是大于而不是大于等于?因为是从0开始计数的,实质应为第n+1位)该算法的时间复杂度为O(N),当N很大时(如N = 10 ^ 11)往往会超时。

方法2;

我们令f(m)表示"从0~长度为m的最大的数字"的数字个数之和,由此我们可以继续分析:

f(0) = 0

f(1) =10 + 0 = 10 (对应0 ~ 9)

f(2) =90 * 2 + f(1) = 190 (对应10 ~99, 0 ~ 9)

f(3) =900 * 3 + f(2) = 2890 (对应100 - 999,0 ~ 99)

f(4) = 9000 * 4 + f(3) =38890 (对应1000 ~ 9999,0 ~ 999)

f(m) = 9 * 10^(i - 1) * m + f(m-1)

其中m表示数字的长度。求出f(m)之后,剩下的就比较好解了。

对于数字n,我们只需要比较n与数组f中每个元素,如果f(k) >= n,其中k是满足前面条件的最小值,那么我们就可以确定最终的数字长度一定是k了。所以令n = n - f(k - 1),然后根据n / k和n % k的结果,就能知道最终的数字R和R中的哪个位置。

举个例子:

假设 n = 1001,由于f(2) < 1001且f(3) > 1001,所以最终的数字一定是3位数的数字。令n = n - f(2) = 811。有811 / 3 =270 ,811 % 3 = 1。所以最终的数字为100 + 270 = 370,且是370中的第1位数(从0开始计数),所以最终的结果是7。

具体代码如下:

class Solution
{
public:
	int countOfIntegers(int digits)
	{
		if (digits == 1)
			return 10;
		int count = (int)std::pow(10, digits - 1);
			return 9 * count;
	}
	int digiAtIndex(int index)
	{
		if (index < 0)
			return -1;
		int digits = 1;
		while (true)
		{
			int numbers = countOfIntegers(digits);
			if (index < numbers*digits)
				return digiAtIndex(index, digits);
			index -= digits * numbers;
			digits++;
		}
	}
	int digiAtIndex(int index, int digits)
	{		
		int Remin = index % digits;
		int numbers = beginNumber(digits) + index / digits;
		int indexFromRight = digits - index % digits;
		for (int i = 1; i < indexFromRight; ++i)		
			numbers /= 10;		
		return numbers % 10;	
	}
	int beginNumber(int digits)
	{
		if (digits == 1)
			return 0;
		return (int)std::pow(10, digits - 1);
	}
};
  1. 时间复杂度:digiAtIndex函数中有一个循环,其他函数复杂度均为O(1)
  2. 空间复杂度:O(1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值