Skip to content

Conversation

hroc135
Copy link
Owner

@hroc135 hroc135 commented Mar 20, 2025

- https://github.com/hayashi-ay/leetcode/pull/46/files#diff-da439603310f08640b8dab0ec6cfc15251b5669e04e4effc5795dbe1f506a8daR13
- O(2^n)の空間計算量でどのくらいのメモリ領域が使われるのかについて見積もっていたので自分もやってみる
- メモリ使用量は2^{n-1}でleetcodeの制約はn <= 30
- int64は8Bなので 2^29 ÷ 8 ≒ 2^30 ÷ 10 ≒ 1000^3 ÷ 10 = 10^8 = 100MB
Copy link

Choose a reason for hiding this comment

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

8で割っているのがよく分かりません。
log_10 2 ~ 0.301 を使うと少し速いです。

Copy link
Owner Author

Choose a reason for hiding this comment

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

スライスの最大要素数が2^29で各要素がint64で8Bなので、×8でした。
$2^{29} × 8 = 2^{32} = (10^{\log_{10}2})^{32} \approx (10^{0.301})^{32} \approx 10^9$ で1GB程度になりそうです。


#### 2a
- step1の修正
- 0なら1に、1なら0にの反転はもっと簡単にできる
Copy link

Choose a reason for hiding this comment

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

true false で not であるという考え方もあります。

Copy link
Owner Author

Choose a reason for hiding this comment

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

書いてみました。

func kthGrammar(n int, k int) int {
	var kthGrammarHelper func(n int, k int) bool
	kthGrammarHelper = func(n int, k int) bool {
		if n == 1 {
			return false
		}
		rowHalfSize := int(math.Pow(2, float64(n-2)))
		if k > rowHalfSize {
			return !kthGrammarHelper(n-1, k-rowHalfSize)
		}
		return kthGrammarHelper(n-1, k)
	}

	if kthGrammarHelper(n, k) {
		return 1
	}
	return 0
}

- Hamming Weight を計算するアルゴリズム
- SWAR: SIMD within a Register
- アルゴリズムの中身はあまり理解できなかったが、
ざっくり言うとビットのシフトと0101、0011みたいなビット列とのアンドを繰り返していく感じ
Copy link

Choose a reason for hiding this comment

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

ああ、これは2桁ずつ切って、そこの中で2桁の整数を使ってビットの数を数える、4桁ずつ4桁、8桁ずつ8桁……としています。

Copy link
Owner Author

Choose a reason for hiding this comment

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

なるほどです!改めて手元で8bitで実験したところ、2桁ずつ、4桁ずつ、8桁ずつとビット数が計算されていく様子がわかりました。ありがとうございます。

Copy link

Copy link
Owner Author

Choose a reason for hiding this comment

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

こういう計算を生業にしている方々がいると思うと尊敬です

- currentRowSymbols のサイズは2^kなので内側のループは2^kであることより、
1+2+4+...+2^n という一般項2^nの等比数列の和を求めてO(2^n)
- 空間計算量: O(2^n)
- ヒープメモリ切れでクラッシュした
Copy link

Choose a reason for hiding this comment

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

「ヒープメモリ切れ」という言い方はあまり聞きません。「メモリ溢れ」「メモリ不足」あたりをよく使うと思います。

- Hamming Weight を計算するアルゴリズム
- SWAR: SIMD within a Register
- アルゴリズムの中身はあまり理解できなかったが、
ざっくり言うとビットのシフトと0101、0011みたいなビット列とのアンドを繰り返していく感じ
Copy link

Comment on lines +58 to +61
case n == 2 && k == 1:
return 0
case n == 2 && k == 2:
return 1
Copy link

Choose a reason for hiding this comment

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

ここの分岐はいらないですかね?

Copy link
Owner Author

Choose a reason for hiding this comment

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

はい、不要でした。

if n == 1 {
return 0
}
rowHalfSize := int(math.Pow(2, float64(n-2))) // 2**(n-1) / 2
Copy link

Choose a reason for hiding this comment

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

rowLength = int(math.Pow(2, float64(n-1)))
で変数を置いたあと、if k > rowLength/2 と分岐した方がわかりやすい気もしますが、好みかもしれません

Comment on lines +122 to +123
previousSymbol := kthGrammarHelper(n-1, (k+1)/2)
return patterns[previousSymbol][(k-1)%2]
Copy link

Choose a reason for hiding this comment

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

この辺の(k+1)/2, (k-1)%2の計算が結構追いにくいですが、代案は思い浮かばないし難しいですね

Comment on lines +67 to +69
// if kthGrammar(n-1, k-rowSizeHalf) == 0 then return 1
// if kthGrammar(n-1, k-rowSizeHalf) == 1 then return 0
return (kthGrammar(n-1, k-rowSizeHalf) + 1) & 1

Choose a reason for hiding this comment

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

好みですが、+1に何か意図があるように見えるので、反転処理は 1 - kthGrammar(n-1, k-rowSizeHalf)と書く方が好きです。
ちなみにPythonでは、not使うと反転できたんですが、bool 値になるため int 変換が必要になり、読みづらかったので、1 - self.kthGrammar(n-1, k - half_num_elements)って最終的に書きたくなりました。
https://github.com/olsen-blue/Arai60/pull/47/files#diff-da439603310f08640b8dab0ec6cfc15251b5669e04e4effc5795dbe1f506a8daR9:~:text=%2D%20https%3A//atmarkit,%E3%81%8C%E5%BF%85%E8%A6%81%E3%81%9D%E3%81%86%E3%80%82

Copy link

@olsen-blue olsen-blue Mar 29, 2025

Choose a reason for hiding this comment

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

あ、下で直ってますね。失礼しました。

Comment on lines +99 to +102
if k > rowHalfSize {
return 1 - kthGrammar(n-1, k-rowHalfSize)
}
return kthGrammar(n-1, k)
Copy link

@olsen-blue olsen-blue Mar 29, 2025

Choose a reason for hiding this comment

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

好みですが、等価なことを別々にやる時は if/else を使い、早期returnや特別な場合をキャッチするという時だけ if 単独で書きたい、みたいな気持ちがあります。
(また、elseは、残り全部丸投げという投げやりな気持ちで使う時もありますね。)

Copy link
Owner Author

Choose a reason for hiding this comment

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

使い分けの気持ちわかります。
今回は中身が return 文だけなのに if/else で書くと冗長に見える気がしてインデントを下げました。3項演算子が欲しくなるところですが、残念ながら Go にはありません。最近3項演算子は目読みにくいと言う意見を複数人から伺いましたが、自分は Python は左から右に読めないので使用を控え、条件式 : trueの場合 ? falseの場合 と言う形の言語では使いたくなります。

if k > rowHalfSize {
	return 1 - kthGrammar(n-1, k-rowHalfSize)
} else {
	return kthGrammar(n-1, k)
}

Comment on lines +122 to +123
previousSymbol := kthGrammarHelper(n-1, (k+1)/2)
return patterns[previousSymbol][(k-1)%2]

Choose a reason for hiding this comment

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

子ノード(n, k)の親ノードは(n-1, (k+1) // 2)の位置のノードになりますね。
k の偶奇によって、親の値を反転するかどうかを選択する感じでも書けました。(Step3です)
https://github.com/olsen-blue/Arai60/pull/47/files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants