遞迴 | 第k個語法符號(Python)

Nonino發表於2020-12-01

在第一行我們寫上一個 0。接下來的每一行,將前一行中的0替換為01,1替換為10。

給定行數 N 和序數 K,返回第 N 行中第 K個字元。(K從1開始)

例子:

輸入: N = 1, K = 1
輸出: 0

輸入: N = 2, K = 1
輸出: 0

輸入: N = 2, K = 2
輸出: 1

輸入: N = 4, K = 5
輸出: 1

解釋:
第一行: 0
第二行: 01
第三行: 0110
第四行: 01101001

注意:

N 的範圍 [1, 30].
K 的範圍 [1, 2^(N-1)].

連結:https://leetcode-cn.com/problems/k-th-symbol-in-grammar

暴力法

class Solution(object):
    def kthGrammar(self, N, K):
        rows = []
        lastrow = '0'
        while len(rows) < N:
            rows.append(lastrow)
            lastrow = "".join('01' if x == '0' else '10'
                              for x in lastrow)
        return int(rows[-1][K-1])

遞迴法(父子遞迴)

class Solution(object):
    def kthGrammar(self, N, K):
        if N == 1: return 0
        return (1 - K%2) ^ self.kthGrammar(N-1, (K+1)//2)
        #第 K 個數字是上一行第 (K+1) // 2 個數字生成的, (1-K%2)是因為如果上一行的數字為 0,被生成的數字為 1 - (K%2),如果上一行的數字為 1,被生成的數字為 K%2. 
        #位異或用的很巧妙,因為0,1生成的'0','1'順序剛好相反,因此只要一個判斷條件,相對應的,位異或看K%2,得到的數字剛好就是奇數位'1',偶數位'0', 如果上一行的相應數字是1,則得到奇數位'0',偶數位'1',即對應'01',矛盾, 故選擇 1-K%2. 

轉換為二進位制運算

class Solution(object):
    def kthGrammar(self, N, K):
        return bin(K - 1).count('1') % 2  #翻轉的次數等於 K-1 二進位制表示形式中 1 出現的個數

參考:https://leetcode-cn.com/problems/k-th-symbol-in-grammar/solution/di-kge-yu-fa-fu-hao-by-leetcode/

相關文章