1. 程式人生 > 實用技巧 >劍指 Offer 17. 列印從1到最大的n位數

劍指 Offer 17. 列印從1到最大的n位數

  • 題目描述

輸入數字 n,按順序打印出從 1 到最大的 n 位十進位制數。比如輸入 3,則打印出 1、2、3 一直到最大的 3 位數 999。

示例 1:

輸入: n = 1
輸出: [1,2,3,4,5,6,7,8,9]

說明:

用返回一個整數列表來代替列印
n 為正整數

  • 分析

簡單做法這裡就不記錄了,雖然在python裡面不考慮大數越界問題,但是面試的時候要是就僅僅手寫個for迴圈+append,肯定offer就涼了。

參照題解:https://leetcode-cn.com/problems/da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/solution/mian-shi-ti-17-da-yin-cong-1-dao-zui-da-de-n-wei-2/

因此,可以考慮將列印數的問題轉化為列印string的全排列問題,可以看這個圖理解排列過程:

就是從n位到各位逐漸求0~9的排列組合。因此可以用遞迴實現,遞迴的思想是:

向低位遞迴,當個位已經被固定時,新增數字的字串,例如n=2時,固定十位0~9,遞迴最小規模為當遞迴到個位數時,新增數字字串。

但是,僅僅這樣輸出的是元素為string的list,並且存在01 02 010 099 這樣的前面帶0的數,因此我們還需要去前面的0才是最終的打印出來正常的數字。

(這裡其實我就理解得不是很透徹了)

刪除高位數字:

1.字串左邊界定義:設定start為左邊界,用nums[start:]控制輸出的不為零的數

2.左邊界start的變化規律:

觀察可知,當輸出數字的所有位都是 99 時,則下個數字需要向更高位進 11 ,此時左邊界 startstart 需要減 11 (即高位多餘的 00 減少一個)。例如當 n = 3n=3 (數字範圍 1 - 9991−999 )時,左邊界 start 需要減 1的情況有: "009" 進位至 "010" , "099" 進位至 "100" 。設數字各位中 99 的數量為 nine,所有位都為 99的判斷條件可用以下公式表示:

nstart=nine

3.統計nine的方法:固定第x位,當i=9,則nine=nine+1,並且一定要在回溯前回復nine=nine-1

程式碼

class
Solution: def printNumbers(self, n: int) -> [int]: def dfs(x): if x == n: # 終止條件:已固定完所有位 s = ''.join(num[self.start:]) #res.append(''.join(num)) # 拼接 num 並新增至 res 尾部 if s != '0': res.append(int(s)) if n - self.start == self.nine: self.start -= 1 return for i in range(10): # 遍歷 0 - 9 if i == 9: self.nine += 1 num[x] = str(i) # 固定第 x 位為 i dfs(x + 1) # 開啟固定第 x + 1 位 self.nine -= 1 num = ['0'] * n # 起始數字定義為 n 個 0 組成的字元列表 res = [] # 數字字串列表 self.nine = 0 self.start = n -1 dfs(0) # 開啟全排列遞迴 return res