Skip to content

22.Generate Parentheses#50

Open
tom4649 wants to merge 3 commits intomainfrom
22.Generate-Parentheses
Open

22.Generate Parentheses#50
tom4649 wants to merge 3 commits intomainfrom
22.Generate-Parentheses

Conversation

@tom4649
Copy link
Copy Markdown
Owner

@tom4649 tom4649 commented Apr 20, 2026

Comment thread 22.Generate-Parentheses/sol2.py Outdated
Comment on lines +3 to +4
if n == 0:
return []
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

この問題では不要ですが、どちらかというとsol3のように、[""]を返す方が正しそうな気がしますね。

if n == 0:
return []

parentheses = []
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

parenthesisと見間違えそうです。parenthesisにも複数の括弧がありますし、意味もやや曖昧ですね。

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.

ご指摘の通りだと思います。
parenthesisはprefixに、parenthesesの方をresultsとしました。

return
if left_used < n:
parenthesis += "("
generate_parenthesis_from(parenthesis, left_used + 1, right_used)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

sol1のようにparenthesis + "("としない理由はありますか?

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.

バックトラックを意識して書いたためです

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

listで文字を貯めて、最後にjoinしたら良さそうですかね。現状は新しいstrオブジェクトを作り直しているだけの意図が不明な無駄な操作に見えます。

Copy link
Copy Markdown
Owner Author

@tom4649 tom4649 Apr 22, 2026

Choose a reason for hiding this comment

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

やっと意図が分かりました。strはimmutableでしたね。
listに直した方が良さそうですので修正しました。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

文字列のコピーは割と速く、どうせ、このプログラムは n がカタラン数で増加するので20くらいがせいぜいでしょう。そう考えるとあまり大きな問題ではないかもしれません。どれくらい速くなっているかは計測してもいいでしょう。

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.

ほぼ変わらない、というかrevisedが遅い場合の方が遅かったです。答えの数が大きいことによってjoinを毎回行うオーバーヘッドが大きくなっていそうです。意外な結果でした。

for i in range(n):
for A in self.generateParenthesis(i):
for B in self.generateParenthesis(n - 1 - i):
result.append("({}){}".format(A, B))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

f-stringが使えますね。

Copy link
Copy Markdown
Owner Author

@tom4649 tom4649 Apr 22, 2026

Choose a reason for hiding this comment

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

f-stringの方が可読性が良さそうですね。こちらに書き換えました。

class Solution:
@functools.cache
def generateParenthesis(self, n: int) -> List[str]:
# Valid parentheses must be written in the form of (A)B, where A and B are valid parentheses uniquely.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

context-free grammarですね。
S -> (S)S | ε

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.

確かにそうですね。ただ、この問題では「一意に書ける」ことが重要なのではないかと思いました。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

すみません、「ただ」以降のつながりがよく分かりませんでした。単にCFGですねというコメントでした。

Copy link
Copy Markdown
Owner Author

@tom4649 tom4649 Apr 22, 2026

Choose a reason for hiding this comment

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

なるほど、CFGであるか否かを意識するようにしようと思います。

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

Choose a reason for hiding this comment

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

全ての有効な括弧列を生成でき、かつ、ambiguousではない文法なら、漏れなく重複なしで生成できますね。

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        parens = [[] for _ in range(n + 1)]
        parens[0].append('')
        for size in range(1, n + 1):
            for inside_size in range(size):
                right_size = size - inside_size - 1
                for inside in parens[inside_size]:
                    for right in parens[right_size]:
                        parens[size].append(f'({inside}){right}')
        return parens[n]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

あ、そうですね。unambiguous という条件をつければ抜け漏れないですね。

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.

文字列操作の問題が出たときにCFGや正規表現、曖昧な言語かどうかは意識しようと思います。

このコードを見て気がつきましたが、この問題はカタラン数の漸化式が自然に連想されますね。
S -> (S)S | εの規則から答えの長さがカタラン数になることも分かりますね。

return []

parentheses = []
frontier = [("(", 1, 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.

自分なら("", 0, 0) から始めるのですが、趣味の範囲だと思います。

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.

たしかにその書き方もできますね。考えていませんでした。

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.

4 participants