劍指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——名企面試官精講典型編程題

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