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