From 801cd06d1411afd93a927c2ef27d42d9050454ea Mon Sep 17 00:00:00 2001 From: tom4649 Date: Mon, 13 Apr 2026 14:28:00 +0900 Subject: [PATCH] first step --- 779.K-th-Symbol-in-Grammar/memo.md | 54 ++++++++++++++++++++++++++++++ 779.K-th-Symbol-in-Grammar/sol1.py | 10 ++++++ 779.K-th-Symbol-in-Grammar/sol2.py | 13 +++++++ 779.K-th-Symbol-in-Grammar/sol3.py | 3 ++ 4 files changed, 80 insertions(+) create mode 100644 779.K-th-Symbol-in-Grammar/memo.md create mode 100644 779.K-th-Symbol-in-Grammar/sol1.py create mode 100644 779.K-th-Symbol-in-Grammar/sol2.py create mode 100644 779.K-th-Symbol-in-Grammar/sol3.py diff --git a/779.K-th-Symbol-in-Grammar/memo.md b/779.K-th-Symbol-in-Grammar/memo.md new file mode 100644 index 0000000..d9c3b94 --- /dev/null +++ b/779.K-th-Symbol-in-Grammar/memo.md @@ -0,0 +1,54 @@ +# 779. K-th Symbol in Grammar + +紙に書いて考えてみると、問題の条件は + +1. 前半分の文字列は前の行の文字列 +2. 後半分の文字列は前半分の文字列のflip +3. 最初(n=1)が0 + +で特徴づけられることに気が付く。(おそらく同値だと思う) + +これを用いて再帰を書く: sol1.py + +再帰を使わずに書く場合も考える: sol2.py + +## コメント集 + +https://discord.com/channels/1084280443945353267/1200089668901937312/1216054396161622078 + +> 実は、ビットの数を調べるのは、たまに大事で、有名なアルゴリズムがあります。 + +> ビット演算だけでできる計算って実はかなり豊かなんですよね。 + +https://stackoverflow.com/questions/109023/count-the-number-of-set-bits-in-a-32-bit-integer#109025 +これを読んでみる + +二進表現で 1 が立っているビットの個数(Hamming weight / population count / popcount)を数えるアルゴリズムについての議論 + +- CPU次第で一番速いのは違う +- GCC 10 / Clang 10 以降は、ハードウェアの popcount に置き換えられる +- SWARアルゴリズム +``` +i = i - ((i >> 1) & 0x55555555); # (i & 0x55555555) + ((i >> 1) & 0x55555555)に等しい。0x55555555は1010...101なので偶数ビットと基数ビットを足している +i = (i & 0x33333333) + ((i >> 2) & 0x33333333); #二ビットごとの {0, 1, 2} の和を4ビットごとに {0, 1, 2, 3, 4}の和にまとめる +i = (i + (i >> 4)) & 0x0F0F0F0F; 同様に4ビットごとの和を8ビットにまとめる + +i *= 0x01010101; # i + (i<<8) + (i<<16) + (i<<24)に等しい。最上位の8ビットにまとめる +return i >> 24; # まとめた和を取り出す +``` + + + +https://github.com/hayashi-ay/leetcode/pull/46 + +> 出力は n の値に依存しません。その点を考慮し、もう少し効率の良い回答を考えてみても良いかもしれません。ただ、そこまで踏み込むと、ただの数学パズルのため、踏み込まなくても良いかもしれません。 + +たしかに sol2.pyの操作は n に依存しない。さらに最後に1が余る性質を利用すれば1を引いてから考えれば良いのか + +組み込み関数 int.bit_countを使う +https://docs.python.org/ja/3/library/stdtypes.html#int.bit_count + + +https://github.com/hroc135/leetcode/pull/44/changes/BASE..caccade39f42ccaeac9b6b2e5d981ace708ffc3b#diff-51246bfe90de9312497a14a935a13980cce9e8a58b9614c7d17f48d8ac78129a + +最後のメモが参考になった diff --git a/779.K-th-Symbol-in-Grammar/sol1.py b/779.K-th-Symbol-in-Grammar/sol1.py new file mode 100644 index 0000000..dbf835b --- /dev/null +++ b/779.K-th-Symbol-in-Grammar/sol1.py @@ -0,0 +1,10 @@ +class Solution: + def kthGrammar(self, n: int, k: int) -> int: + num_char = 2 ** (n - 1) + if k <= 0 or k > num_char: + raise ValueError(f"Invalid input k: {k}, n: {n}") + if n == 1: + return 0 + if k > num_char // 2: + return 1 - self.kthGrammar(n - 1, k - num_char // 2) + return self.kthGrammar(n - 1, k) diff --git a/779.K-th-Symbol-in-Grammar/sol2.py b/779.K-th-Symbol-in-Grammar/sol2.py new file mode 100644 index 0000000..e991b70 --- /dev/null +++ b/779.K-th-Symbol-in-Grammar/sol2.py @@ -0,0 +1,13 @@ +class Solution: + def kthGrammar(self, n: int, k: int) -> int: + if n == 1: + return 0 + num_flip = 0 + half_length = 2 ** (n - 2) + while half_length > 0: + if k > half_length: + num_flip += 1 + k -= half_length + half_length //= 2 + assert k == 1 + return num_flip % 2 diff --git a/779.K-th-Symbol-in-Grammar/sol3.py b/779.K-th-Symbol-in-Grammar/sol3.py new file mode 100644 index 0000000..299cb02 --- /dev/null +++ b/779.K-th-Symbol-in-Grammar/sol3.py @@ -0,0 +1,3 @@ +class Solution: + def kthGrammar(self, n: int, k: int) -> int: + return (k - 1).bit_count() % 2