Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions 779. K-th Symbol in Grammar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# 進め方

Step1 : 問題を解く。

Step2 : 他の人のPRを参照し、コメントする。

Step3 : 3回続けてエラーが出ないように書く。ドキュメントを参照する。

# 実践

## Step1

### 思考ログ

入力が小さければ愚直にやってもいけそう。

O(2 ** n)なのでn=30だととても厳しい。

2の20乗が100万くらいなのでPythonだと2**10秒程度かかる

全く思いつかないですね

## Step2

### 同じ問題を解いた人のプルリクを見る

https://github.com/olsen-blue/Arai60/pull/47

- この問題もっとマクロな話をするとビットカウントの偶奇になっていますよ。二分木を考えて、右に行くとビットが反転して、左に行くとしないということですね。
- 「ある行は一つ前の行をコピーしてから反転させたものをくっつけた形になっている。」
- なるほど、法則性があったのか。

0

01

0110

01101001

なるほど、nを使わずに求められそう。

> kの値にどう結びつくのかイメージできずでしたが、k-1 の二進数表記はルートからの移動パターンなんですね。
k=5 (k-1=4, 二進数 100)だと、右(1)->左(0)->左(0)ですね。なので、k-1のビットを数えて偶奇を調べれば良いんですね。
>

なるほど

bitと二分木が繋がるのすごい。

```python
class Solution:
def kthGrammar(self, n: int, k: int) -> int:
return (k - 1).bit_count() & 1
```

```python
class Solution:
def kthGrammar(self, n: int, k: int) -> int:
if n == 1:
return 0

return self.kthGrammar(n - 1, (k + 1) // 2) ^ (k % 2 == 0)
```

bit反転に1 - x を使うのとx ^ 1 どちらがよいのだろうか。

notはちょっと嫌だなという気持ちです。

https://github.com/TORUS0818/leetcode/pull/48/files

- whileで書く。
- これは確かに再帰のほうが分かりやすいかも

```python
class Solution:
def kthGrammar(self, n: int, k: int) -> int:
result = 0

while n > 1:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while k > 1: で良さそうです。bit_count を使った解法で n に対して何もしないのと一緒で、k <= 2**(n-1) さえ分かっていればあとは k に対してのみ処理すればよいです。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます!言われてみればそうですね!

n -= 1
if k % 2 == 1:
k = (k + 1) // 2
continue
result ^= 1
k //= 2
return result
```

https://github.com/hroc135/leetcode/pull/44/files

- bitの内部実装を読んでいる。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ビットを数えるのは CPU によっては専用の命令が用意されていたりするので、それの一番下のビットを見るだけの場合もありますね。

- Arai60が終わったら、毎日少しずつCpythonとかを読みたいなあ。

## Step3

### 3回連続で再現できるように

bit演算マシマシ

```python
class Solution:
def kthGrammar(self, n: int, k: int) -> int:
if n == 1:
return 0
return self.kthGrammar(n - 1, (k + 1) // 2) ^ ((k & 1) ^ 1)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

自分なら ^ (k % 2 == 0) にすると思いました。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あ、下に書いてありましたね。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここまでやると読みにくいですね。

```

notを使ってみた

```python
class Solution:
def kthGrammar(self, n: int, k: int) -> int:
if n == 1:
return 0
result = self.kthGrammar(n-1, (k+1) // 2)
return result ^ (not k % 2)
```

これが一番わかりやすいかな

```python
class Solution:
def kthGrammar(self, n: int, k: int) -> int:
if n == 1:
return 0
result = self.kthGrammar(n-1, (k+1) // 2)
return result ^ (k % 2 == 0)
```

bit演算なぜか好きです