-
Notifications
You must be signed in to change notification settings - Fork 0
22. Generate Parentheses #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- おお!感動 | ||
- 問題の分解の仕方を変えるだけでこんなにすっきり書けてしまうとは | ||
- https://sentry.io/answers/concatenating-strings-in-go/ | ||
- strings.Builder で用意したバッファに WriteString で書き込むとコピーせずに string を結合できるらしい |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strings.Builder でコピーがされないので速いというのは一般論としては正しいです。
ただ、a, b ももう string になっているので、もうコピーされているわけですね。
そうすると、高階関数を使うことになるでしょう。
そこで DeepSeek に書かせました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func generateFunctionsToAppendParenthesis(n int) []func(*strings.Builder) {
if n == 0 {
return []func(*strings.Builder){func(sb *strings.Builder) {}}
}
result := []func(*strings.Builder){}
for i := 0; i < n; i++ {
aFuncs := generateFunctionsToAppendParenthesis(i)
bFuncs := generateFunctionsToAppendParenthesis(n - i - 1)
for _, a := range aFuncs {
for _, b := range bFuncs {
aCopy := a
bCopy := b
fn := func(sb *strings.Builder) {
sb.WriteString("(")
aCopy(sb)
sb.WriteString(")")
bCopy(sb)
}
result = append(result, fn)
}
}
}
return result
}
func executeFunctions(funcs []func(*strings.Builder)) []string {
result := make([]string, 0, len(funcs))
for _, f := range funcs {
var sb strings.Builder
f(&sb)
result = append(result, sb.String())
}
return result
}
func generateParenthesis(n int) []string {
funcs := generateFunctionsToAppendParenthesis(n)
results := executeFunctions(funcs)
return results
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
元のコードだと、for _, a := range generateParenthesis(i)
で a に string がアサインされているので、コピーが生じてしまうということですね。
高階関数解読中です。
if n == 0 { | ||
return []string{} | ||
} | ||
if n == 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
一応n == 1の処理はなくても動きますね
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
n == 0 のときに空の配列を返しているため、n == 1 の処理がないと for _, p := range previousParenthesis のループが一度も回らないです。n == 0 のときに return []string{""}
を返せば n==1 の処理がなくても動きます。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
確かにそうですね(まだ脳内シミュレーション能力が足りない、、)
どっちが自然かというと、微妙ですね
nextParenthesis[newParenthesis] = struct{}{} | ||
for j := range len(p) { | ||
if p[j] == '(' { | ||
newParenthesis = p[:j+1] + "()" + p[j+1:] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
L27、28とL35、36をなくす代わりに、forループの範囲を伸ばして、最初か最後、もしくはp[j] = '('なら'()'を挿入する、というのを考えましたが、今の実装の方がむしろ簡潔そうですね。
- 手でやることをコードで再現したらできた。嬉しい。成長を感じる | ||
- 手でやったところ、n=i で生成された parenthesis を基に n=i+1 のものを生成するが、 | ||
どうしても重複なく生成する方法を思いつかなかったので、map に格納していくことにした | ||
- "(())" を基に次の parenthesis を生成するなら、頭と末尾に "()" を付けたやつ("()(())", "(())()")と、 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
自分のメモ代わりに書いている文章にコメントするのも変ですが、これ最初のカッコと最後のカッコは、(A, B)でペアという意味のカッコですね(やや混乱しました)
https://leetcode.com/problems/generate-parentheses/description/