leetcode-38:外觀數列
阿新 • • 發佈:2021-02-01
技術標籤:演算法python正則表示式pythonleetcode演算法
LC 外觀數列
題目:
給定一個正整數 n ,輸出外觀數列的第 n 項。
「外觀數列」是一個整數序列,從數字 1 開始,序列中的每一項都是對前一項的描述。
你可以將其視作是由遞迴公式定義的數字字串序列:
countAndSay(1) = "1"
countAndSay(n) 是對 countAndSay(n-1) 的描述,然後轉換成另一個數字字串。
前五項如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
第一項是數字 1
描述前一項,這個數是 1 即 “ 一 個 1 ”,記作 "11"
描述前一項,這個數是 11 即 “ 二 個 1 ” ,記作 "21"
描述前一項,這個數是 21 即 “ 一 個 2 + 一 個 1 ” ,記作 "1211"
描述前一項,這個數是 1211 即 “ 一 個 1 + 一 個 2 + 二 個 1 ” ,記作 "111221"
要 描述 一個數字字串,首先要將字串分割為 最小 數量的組,每個組都由連續的最多 相同字元 組成。然後對於每個組,先描述字元的數量,然後描述字元,形成一個描述組。要將描述轉換為數字字串,先將每組中的字元數量用數字替換,再將所有描述組連線起來。
例如,數字字串 “3322251” 的描述如下圖:
示例 1:
輸入:n = 1
輸出:"1"
解釋:這是一個基本樣例。
示例 2:
輸入:n = 4
輸出:"1211"
解釋:
countAndSay(1) = "1"
countAndSay(2) = 讀 "1" = 一 個 1 = "11"
countAndSay(3) = 讀 "11" = 二 個 1 = "21"
countAndSay(4) = 讀 "21" = 一 個 2 + 一 個 1 = "12" + "11" = "1211"
解題
方法一:遞迴
def countAndSay(self, n: int) -> str:
if n == 1:
return '1'
s = self.countAndSay(n-1)
i, res = 0, ''
for j, c in enumerate(s):
if c != s[i]:
res += str(j-i) + s[i]
i = j
res += str(len(s) - i) + s[-1] # 最後一個元素莫忘統計
return res
方法二:迭代
def countAndSay(self, n: int) -> str:
res = '1'
for _ in range(n-1): # 控制迴圈次數
i, tmp = 0, ''
for j, c in enumerate(res):
if c != res[i]:
tmp += str(j-i) + res[i]
i = j
res = tmp + str(len(res) - i) + res[-1]
return res
方法三:正則表示式:提取元素
def countAndSay(self, n: int) -> str:
if n == 1:
return '1'
s = self.countAndSay(n-1)
p = r'(\d)\1*'
pattern = re.compile(p)
res = [_.group() for _ in pattern.finditer(s)] # 提取結果
return ''.join(str(len(c)) + c[0] for c in res) # join 內部的 str(len(c)) + c[0] for c in res 是生成器型別
字串 (\d)\1*
可以用來匹配結果。這裡用來提取連在一塊的元素, 如 '111221'
,提取出的元素是 res = ['111', '22', '1']。
然後再返回我們要組裝的字串。
方法四:正則表示式:元素替換
def countAndSay(self, n: int) -> str:
res = '1'
p = r'(\d)\1*'
pattern = re.compile(p)
for _ in range(n-1):
res = pattern.sub(lambda x: str(len(x.group())) + x.group(1), res) # 替換
return res
對於該句:res = pattern.sub(lambda x: str(len(x.group())) + x.group(1), res)
,還是拿上面的舉例,對於 111221
的第一個匹配項 111
,其中 group()
匹配的是 111
(全域性匹配),而 group(1)
匹配到的是 1
(第一個捕獲組,三個 1 中的第一個)。