剑指offer系列-面试题44 - 数字序列中某一位的数字(python)

1. 题目

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

2. 解题思路

2.1 常规思路

从0开始枚举每个数字,每枚举一个数字的时候,求出该数字是几位数(如15是2位数,9323是4位数);
把该数字的位数和前面所有数字的位数的位数累加。
比较位数之和与输入的数字n,若小于等于这个n,则继续往下枚举数字;
若大于n,那么第n位数字一定是所枚举的这个数字中的某一位,再从该数字中找到对应的那一位。

很明显,这个思路需要一个数字一个数字的往下递推,每个数字都要去判断。

2.2 书中的思路

举个例子来分析,找到思路。例如,序列中的第1001位是什么?

序列中的1位数是 0~9 ,共10个。1001 大于 1 * 10 ,因此,这个数一定在0 ~ 9 之后;
序列中的2位数是 10 ~ 99 ,共90个。(1001 - 1 * 10) = 991 大于 2 * 90,因此,这个数一定在 10 ~ 99 之后;
序列中的3位数是 100 ~ 999,共900个。(1001 - 1 * 10 - 2 * 90) = 811 小于 3 * 900,因此,这个数一定在 100 ~ 999 之间;

步骤

1.确定所求数位的所在数字的位数
2.确定所求数位所在的数字
3.确定所求数位在 numnum 的哪一数位

3. 代码实现

这里只写书上这种思路的代码实现。

def digit_at_index(index):
	"""
	:param index: 格式化序列中的第几个数字,从0开始计数
	:return int: 该index对应的数字
	"""
	if index < 0:
		return -1
	
	digit = 1
	while True:
		numbers = count_of_integers(digit)
		if index < numbers * digit: # 这些位数为digit的数字总共占据了多少位置
			return find_digit(index, digit)
		index -= digit * numbers
		digit += 1
	return -1

def count_of_integers(digit):
	"""
	根据输入的数字,判断digit位的数字有多少个
	:param digit: 数字的位数
	:return int:
	"""
	if digit == 1:
		return 10
	return 9 * pow(10, digit-1) # 效率较下行方式更高
	#return 9 * (10 ** (digit-1))

def find_digit(index, digit):
	"""
	:param index: 在格式化序列中的第几个数字
	:param digit: 几位数字,就是第index的数字是digi位数字中的某一个
	:param int: 根据这个两个条件得出此index对应的数字是多少
	"""
	number = begin_number(digit) + index // digit
	# index对应的数字应该是number这个数中从右往左的第index_from_right这个数字
	index_from_right = digit - index % digit

	for i in range(1, index_from_right):
		number //= 10
	return number % 10

def begin_number(digit):
	"""
	获取digit位数字的中的第一个数字是多少
	:param digit: 数字位数
	:return int: 在digit位数字中的第一个数字
	"""
	if digit == 0:
		return 0
	return pow(10, digit-1)
	#return 10 ** (digit-1)

3.2 精简版

class Solution:
    def findNthDigit(self, n: int) -> int:
        digit, start, count = 1, 1, 9
        while n > count: # 1.确定所求数位的所在数字的位数
            n -= count
            start *= 10
            digit += 1 # 数字的位数
            count = 9 * start * digit
        num = start + (n - 1) // digit # 2.确定所求数位所在的数字
        return int(str(num)[(n - 1) % digit]) # 3.确定所求数位在 numnum 的哪一数位

作者:jyd
链接:https://leetcode-cn.com/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/solution/mian-shi-ti-44-shu-zi-xu-lie-zhong-mou-yi-wei-de-6/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

4. 总结

有没有发现最近的几道题都是,找出规律才能得到最好的算法,一般一开始想到的算法,复杂度过高,效率不太行。

5. 参考文献

[1] 剑指offer丛书
[2] 剑指Offer——名企面试官精讲典型编程题

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章