diff --git a/Python3/779. K-th Symbol in Grammar.md b/Python3/779. K-th Symbol in Grammar.md new file mode 100644 index 0000000..a04e154 --- /dev/null +++ b/Python3/779. K-th Symbol in Grammar.md @@ -0,0 +1,93 @@ +## Step 1. Initial Solution + +- n行目のk番目の数値だけ分かれば良いので規則性を見つけたい + - 0 + - 01 + - 0110 + - 01101001 + - … +- 2^(n-1)個の中でk番目 + - 2で割れば変換前の行の位置が分かる + - 1個前の数値が分かればkを2で割った余りから分かる + +```python +class Solution: + def kthGrammar(self, n: int, k: int) -> int: + if n == 1: + return 0 + if self.kthGrammar(n - 1, (k-1) // 2 + 1) == 0: + if k % 2 == 1: + return 0 + return 1 + if k % 2 == 1: + return 1 + return 0 +``` + +### Complexity Analysis + +- 時間計算量:O(n) +- 空間計算量:O(n) + +## Step 2. Alternatives + +- よく見ると、一行前のものを反転したものを足しただけになっている + - 論理的な説明ができないので微妙だが以下のように書ける + - $k<=2^{n-2}$ なら $x_k^n = x_k^{n-1}$ + - $k>2^{n-2}$なら $x_k^n = XOR(x_l^{n-1},1)~~(k=2l~or~2l-1)$ + - 帰納的に考えれば左から中心方向の数列と右から中心方向の数列が一致することは分かる気がするがそれで十分なのか? + + ```python + class Solution: + def kthGrammar(self, n: int, k: int) -> int: + if n == 1: + return 0 + + previous_end = 2**(n-2) + if k <= previous_end: + return self.kthGrammar(n-1, k) + return self.kthGrammar(n-1, k - previous_end) ^ 1 + ``` + +- 型注釈で関数の返り値をintにしているが実際は0か1しか返してはいけないのは違和感があるか? +- https://github.com/tokuhirat/LeetCode/pull/46/files#diff-c46c983729673189187941eeb13f28963e572821bf2ac55e4b03cbf2d99bc737R4 + - 2番目に思い付いたやり方と同じ発想な気がするが再帰ではないので状態変数を持っている感じ + - これに還元できるならkのビット表現の各桁の和の偶奇でいけるか + + ```python + class Solution: + def kthGrammar(self, n: int, k: int) -> int: + bit_sum = 0 + k -= 1 + + while k > 0: + bit_sum += k & 1 + k >>= 1 + + return bit_sum & 1 + ``` + + - 結果的にはこれで行けるが最初には思いつかなかった + - この辺りと一緒 + - https://github.com/tokuhirat/LeetCode/pull/46/files#diff-c46c983729673189187941eeb13f28963e572821bf2ac55e4b03cbf2d99bc737R72-R77 + - https://github.com/fuga-98/arai60/pull/46/files#diff-da439603310f08640b8dab0ec6cfc15251b5669e04e4effc5795dbe1f506a8daR54 + - わざわざwhile文で回していたがbit_countなる関数があるらしい + - `return (k-1).bit_count() & 1` + - https://github.com/olsen-blue/Arai60/pull/47/files#r2003238004 + - 説明はいまいちよくわからないけどこういう書き方もあるのか + +## Step 3. Final Solution + +- 一番しっくり来たもので行く + +```python +class Solution: + def kthGrammar(self, n: int, k: int) -> int: + if n == 1: + return 0 + + previous_row_length = 2 ** (n-2) + if k <= previous_row_length: + return self.kthGrammar(n-1, k) + return self.kthGrammar(n-1, k - previous_row_length) ^ 1 +```