1. 問題描述:
在第一行我們寫上乙個 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
2. 思路分析:
① 一開始最容易想到的是模擬整個過程,從最開始的字串"0"出發,通過迴圈生成第n行的字串,然後返回字串中k - 1的位置的字元對應的整數,但是由於n最大是30生成的字串長度為2 ^ 29,而且我們是在迴圈中模擬依次生成第n行的資料,所以時間複雜度是非常高的
② 除了暴力列舉的方法之外,力扣提供了遞迴的解法,感覺思路挺不錯而且比較容易理解,通過寫出前面若干行的資料可以發現乙個規律就是:第 k 個數字是上一行第 (k+1) / 2 個數字生成的。如果上一行的數字為 0,被生成的數字為 1 - (k%2),如果上一行的數字為 1,被生成的數字為 k%2,所以我們可以利用遞迴從第n行開始往上找,利用遞迴層層返回的特點就可以求解最終第n第k個的數字,並且使用遞迴尋找的時候資料規模在一步步減小,根據下面力扣提供的圖就比較好理解遞迴的過程了
③ 除了這個規律之外,還可以發現乙個很明顯的規律是對於當前行前半部分與後半部分為翻轉的關係,所以我們可以利用這個規律使用遞迴解決即可,如果當前找的第n行中的第k個資料位於第n行的後半部分那麼第k個數字就位前半部分數字對應的映象,我們只需要找到前部部分對應的數字然後對其異或即可得到位於後半部分的第k個數字,如果當前找的第n行中的第k個資料位於第n行的前半部分那麼直接在前半部分找即可。其中第n行的長度為2 ^ (n - 1),映象為2 ^ (n - 2),後半部分對應的映象為k - 2 ^ (n - 2),畫出具體的例子就比較清楚了
3. **如下:
暴力(超時):
class solution:
def kthgrammar(self, n: int, k: int) -> int:
pre, res = "0", ""
for i in range(n):
for j in range(len(pre)):
if pre[j] == "0":
res += "01"
else:
res += "10"
pre = res
res = ""
return int(pre[k - 1])
遞迴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)
遞迴2:
import math
class solution:
def kthgrammar(self, n: int, k: int) -> int:
if n == 1: return 0
if k <= int(math.pow(2, n - 2)):
return self.kthgrammar(n - 1, k)
else:
return 1 ^ self.kthgrammar(n - 1, k - int(math.pow(2, n - 2)))
779 第K個語法符號
在第一行我們寫上乙個 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...
LeetCode 779 第K個語法符號 遞迴解法
在第一行我們寫上乙個 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...
LeetCode779 第K個語法符號
在第一行我們寫上乙個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 第三行 011...