Try an interactive version of this dialog: Sign up at solve.it.com, click Upload, and pass this URL.

Code: 63 ()

import sys
sys.path.append('.')
from leet_utils import lc_setup, get_leetcode_problem, lc_export
lc_setup("https://leetcode.com/problems/invert-binary-tree/", add_cells=True)

Output: 36

✓ Setup complete: 226. Invert Binary Tree

Note: 12

226. Invert Binary Tree

Note: 27

  • URL: https://leetcode.com/problems/invert-binary-tree/
  • Difficulty: Easy

Code: 45 ()

from IPython.display import HTML
problem = get_leetcode_problem("https://leetcode.com/problems/invert-binary-tree/")
HTML(problem["content"])

Output: 504

Given the root of a binary tree, invert the tree, and return its root.

 

Example 1:

Input: root = [4,2,7,1,3,6,9]
Output: [4,7,2,9,6,3,1]

Example 2:

Input: root = [2,1,3]
Output: [2,3,1]

Example 3:

Input: root = []
Output: []

 

Constraints:

  • The number of nodes in the tree is in the range [0, 100].
  • -100 <= Node.val <= 100

Note: 6

Step 1

Note: 337

実装1

  • アルゴリズムの選択
    • 全てのノードの.leftと.rightをswapできればいい。順序はなんでもいい。
    • preorderが最も自然なのでpreorderでやる。
  • 実装
    • recursiveでもiterativeでもいいが、preorderはいわば末尾再帰の形なのでiterativeでも容易にかける。
      • iterativeでやる。
    • Noneチェックをstackにappend前にするか、pop後にするか。
      • どっちでもいいがコード中に分散しないpop後にやる方法で書く。
  • 計算量
    • Time: O(n)
    • Extra Space: O(n)
      • 実装よりここが悩んだ。
      • Noneもappendするのでstackに最大n個入りうるのでO(n)。
      • Noneをappend前に弾くとしたら、O(height)。height <= n/2より結局O(n)。

Code: 193 ()

from typing import Optional


# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        stack = [root]
        while stack:
            node = stack.pop()
            if node is None:
                continue
            node.left, node.right = node.right, node.left
            stack.append(node.left)
            stack.append(node.right)
        return root
        

Note: 48

  • 3分かかった。
  • 振り返り
    • 書いている間、特に何も悩まなかった。

Note: 6

Step 2

Prompt: 24

実装1のコードをレビューして、改善点を教えてください。

Assistant: 666

🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠

実装1のコードをレビューしますね。

良い点:

  • シンプルで読みやすい
  • iterativeで書いているのでstack overflowの心配がない(非常に深い木の場合)
  • Noneチェックをpop後に一箇所でやるのは一貫性があって良い

改善の余地がある点:

  1. Noneをstackに入れるのは少し無駄

    • 毎回2つappendして、次のループでNoneならcontinueする
    • append前にチェックすれば無駄なpush/popを減らせる:
    Copied!
    if node.left: stack.append(node.left)
    if node.right: stack.append(node.right)
    
    • ただし、計算量のオーダーは変わらないので好みの問題
  2. rootNoneのケース

    • 現状でも正しく動く(Noneをpopしてcontinueして終わる)
    • 明示的に最初にチェックする方が意図が明確になる場合もある:
    Copied!
    if not root: return root
    
  3. 再帰版の方がより簡潔

    • この問題は木の深さが実用上問題にならないので、再帰の方がPythonicかも:
    Copied!
    def invertTree(self, root):
        if root:
            root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
        return root
    

総評: 現状の実装で十分良いです。改善点は「もっと良くできる」というより「別のスタイル」という感じですね。iterativeを選んだ理由(末尾再帰的な形)もノートに書かれていて、意図が明確で良いと思います。

何か気になる点はありますか?

Note: 235

  • LLMレビューの感想
    • 特になし。
  • コメント集:空
  • PR
    • https://github.com/ryosuketc/leetcode_grind75/pull/6
    • https://github.com/Ryotaro25/leetcode_first60/pull/71
    • https://github.com/huyfififi/coding-challenges/pull/6
    • https://github.com/rihib/leetcode/pull/26/
    • https://github.com/wf9a5m75/leetcode3/pull/13
    • https://github.com/kzhra/Grind41/pull/6
    • https://github.com/irohafternoon/LeetCode/pull/8

Prompt: 72

上記に他の人が解いたPRをまとめています。それぞれのPRの学習記録とそれについているコメントをあなたがチェックし、PRごとの内容を簡潔にまとめて欲しいです。

Assistant: 2,721

🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠

各PRの内容を確認しますね。まず全てのPRを読み込みます。

Copied!
{
  "id": "toolu_01VfAU6M82oCktUnV27seeTd",
  "call": {
    "function": "read_url",
    "arguments": {
      "url": "https://github.com/ryosuketc/leetcode_grind75/pull/6"
    }
  },
  "result": "'Skip to content\\n\\n## Navigation Menu\\n\\nToggle navigation\\n\\n[ ](/)\\n\\n[ Sign in ](/login?return_t<TRUNCATED>"
}
Copied!
{
  "id": "toolu_011rK6csHMucvniH479xKpti",
  "call": {
    "function": "read_url",
    "arguments": {
      "url": "https://github.com/Ryotaro25/leetcode_first60/pull/71"
    }
  },
  "result": "'Skip to content\\n\\n## Navigation Menu\\n\\nToggle navigation\\n\\n[ ](/)\\n\\n[ Sign in ](/login?return_t<TRUNCATED>"
}
Copied!
{
  "id": "toolu_01F66B3B5DFY9WggCDSYbTMU",
  "call": {
    "function": "read_url",
    "arguments": {
      "url": "https://github.com/huyfififi/coding-challenges/pull/6"
    }
  },
  "result": "'Skip to content\\n\\n## Navigation Menu\\n\\nToggle navigation\\n\\n[ ](/)\\n\\n[ Sign in ](/login?return_t<TRUNCATED>"
}
Copied!
{
  "id": "toolu_01Ps1CifJoYJeGmfsx9TsJE5",
  "call": {
    "function": "read_url",
    "arguments": {
      "url": "https://github.com/rihib/leetcode/pull/26"
    }
  },
  "result": "'Skip to content\\n\\n## Navigation Menu\\n\\nToggle navigation\\n\\n[ ](/)\\n\\n[ Sign in ](/login?return_t<TRUNCATED>"
}
Copied!
{
  "id": "toolu_012wNH7tsjCAQy4YpbYqdKMd",
  "call": {
    "function": "read_url",
    "arguments": {
      "url": "https://github.com/wf9a5m75/leetcode3/pull/13"
    }
  },
  "result": "'Skip to content\\n\\n## Navigation Menu\\n\\nToggle navigation\\n\\n[ ](/)\\n\\n[ Sign in ](/login?return_t<TRUNCATED>"
}
Copied!
{
  "id": "toolu_017hoaZzhyTvU3ua6QS3jdzi",
  "call": {
    "function": "read_url",
    "arguments": {
      "url": "https://github.com/kzhra/Grind41/pull/6"
    }
  },
  "result": "'Skip to content\\n\\n## Navigation Menu\\n\\nToggle navigation\\n\\n[ ](/)\\n\\n[ Sign in ](/login?return_t<TRUNCATED>"
}
Copied!
{
  "id": "toolu_01TvDZpQhZnjxhoUZWEgqR72",
  "call": {
    "function": "read_url",
    "arguments": {
      "url": "https://github.com/irohafternoon/LeetCode/pull/8"
    }
  },
  "result": "'Skip to content\\n\\n## Navigation Menu\\n\\nToggle navigation\\n\\n[ ](/)\\n\\n[ Sign in ](/login?return_t<TRUNCATED>"
}

各PRの内容をまとめます:


1. ryosuketc/leetcode_grind75 PR#6 (C++)

  • 実装: C++でiterativeとrecursive両方
  • コメント:
    • std::moveとGCについての議論 → C++にはGCがない。スタックの自動解放とGCは別物
    • nullptr vs NULLnullptr一択(NULLは問題を起こすことがある)
    • 日本語個人ブログは信頼性に注意、cpprefjp等の公式リファレンスで裏取りを推奨

2. Ryotaro25/leetcode_first60 PR#71 (C++)

  • 実装: 再帰版とBFS版
  • コメント:
    • std::swapを使ってswap→invertの順でも良い
    • root == nullの早期チェックは好みの問題(統一感の議論)
    • using namespace std;を避け、std::queueのように明示する方が実務的

3. huyfififi/coding-challenges PR#6 (Python)

  • 実装: DFS(stack)とBFS(queue)
  • コメント:
    • stackにNoneを入れるか入れないかは好みの範囲
    • ただしBFSでvisitedフラグを出てきた後に立てると急激に遅くなるケースがある
    • a, b = b, aはPythonのイディオムとして積極的に使ってよい

4. rihib/leetcode PR#26 (Go)

  • 実装: 再帰版
  • コメント: odaさんからレビューがあったが詳細は見えず
  • ラベル: Grind75, Blind75, NeetCode150, Easy, Recursion, Stack

5. wf9a5m75/leetcode3 PR#13 (Python)

  • 実装: 再帰版とiterativeの複数パターン
  • コメント:
    • 不要な条件分岐(if right_tree:等)は消せる
    • stackにNoneを入れて出てきたらチェック、でもOK
    • ただしNoneを入れないことでループ回数が減る(僅かだが)ので好み
    • 「どちらでもいい」との結論

6. kzhra/Grind41 PR#6 (C++)

  • 実装: BFS(queue)を中心に複数パターン
  • コメント:
    • 不要なelse節を削除可能
    • if (root->left)のような条件なくても動く
    • queueに全部入れてpop後にnullptrチェックする手もある
    • nullptrなら早めに抜けてネストを浅くする提案

7. irohafternoon/LeetCode PR#8 (C++)

  • 注意: このPRは「Valid Parentheses」の問題で、Invert Binary Treeではありません
  • コメント(参考として):
    • using namespace std;は名前空間を汚すので好まれない
    • mapconst修飾を付けると[]ではなくatでアクセスが必要
    • countよりcontains(C++20)が明示的
    • emplace vs pushの違い(in-place構築 vs コピー/移動)

何か特定のPRについて詳しく知りたい点はありますか?

Prompt: 27

各トピックについて、さらに深掘りして詳しく解説してください。

Assistant: 2,080

🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠

各トピックを深掘りしますね。


1. C++のnullptr vs NULL

NULLは歴史的に0または(void*)0として定義されており、整数としても解釈されうる問題があります:

Copied!
void f(int);
void f(char*);

f(NULL);    // どっちが呼ばれる?→ f(int)が呼ばれてしまうことがある
f(nullptr); // 確実にf(char*)が呼ばれる

nullptrはC++11で導入されたstd::nullptr_t型で、ポインタ型にのみ変換可能。オーバーロード解決で曖昧さが生じません。


2. std::moveとGCの話

C++にはGarbage Collectorがありません。メモリ管理は:

  • スタック変数: スコープを抜けると自動で破棄(RAII)
  • ヒープ変数: newしたらdeleteが必要(またはunique_ptr/shared_ptr

std::moveは「所有権の移動」を示すキャストで、実際にはムーブコンストラクタ/代入演算子を呼び出すためのヒント:

Copied!
std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = std::move(v1);  // v1の中身がv2に移動、v1は空になる

これはGCとは無関係で、コピーを避けてパフォーマンスを上げる仕組みです。


3. using namespace std;を避ける理由

Copied!
using namespace std;  // 名前空間を汚染

問題点:

  • stdには大量の名前がある(count, find, swapなど一般的な名前も)
  • 自分の関数やライブラリの名前と衝突する可能性
  • どこから来た関数か分かりにくくなる

実務では:

Copied!
std::vector<int> v;      // 明示的に書く
std::cout << "hello";    // どこから来たか一目瞭然

競プロでは時間短縮のために使うこともありますが、仕事のコードでは避けるのが一般的です。


4. std::swap vs 手動swap

Copied!
// 方法1: std::swap
std::swap(node->left, node->right);

// 方法2: 手動
auto temp = node->left;
node->left = node->right;
node->right = temp;

std::swapのメリット:

  • 読みやすい、意図が明確
  • 型によっては最適化されたswapが呼ばれる(ムーブセマンティクス対応)

Pythonではa, b = b, aが言語組み込みのイディオムなのでそちらを使います。


5. stackにNone/nullptrを入れるかどうか

入れる派(pop後チェック):

Copied!
stack.append(node.left)   # Noneでも入れる
stack.append(node.right)
# pop後に
if node is None: continue
  • コードがシンプル、append箇所でのチェック不要
  • ループ回数は増える(無駄なpush/pop)

入れない派(append前チェック):

Copied!
if node.left: stack.append(node.left)
if node.right: stack.append(node.right)
  • ループ回数が減る
  • チェックが分散する

計算量のオーダーは同じ(O(n))なので、好みの問題という結論が多いです。


6. BFSでvisitedフラグを「出てきた後」に立てる問題

グラフ探索でのBFS:

Copied!
# ❌ 遅い:出てきた後にvisited
while queue:
    node = queue.popleft()
    if node in visited: continue
    visited.add(node)  # ここで追加
    for neighbor in node.neighbors:
        queue.append(neighbor)

問題:同じノードがqueueに何度も入る可能性がある(特に密なグラフで爆発)

Copied!
# ✅ 速い:入れる前にvisited
while queue:
    node = queue.popleft()
    for neighbor in node.neighbors:
        if neighbor not in visited:
            visited.add(neighbor)  # 入れる前に追加
            queue.append(neighbor)

木ではサイクルがないのでこの問題は起きませんが、一般のグラフでは重要です。


7. emplace vs push

Copied!
std::stack<TreeNode*> s;

s.push(node);     // nodeをコピー/ムーブしてスタックに入れる
s.emplace(node);  // in-placeで構築(コンストラクタ引数を直接渡せる)

ポインタの場合は差がほぼありませんが、オブジェクトの場合:

Copied!
std::vector<std::pair<int, int>> v;

v.push_back(std::make_pair(1, 2));  // pairを作ってからコピー
v.emplace_back(1, 2);               // 直接構築(効率的)

8. count vs contains (C++20)

Copied!
std::unordered_set<int> s = {1, 2, 3};

// C++17以前
if (s.count(2)) { ... }  // 0か1を返す(setの場合)

// C++20以降
if (s.contains(2)) { ... }  // boolを返す、意図が明確

containsの方が「存在確認」という意図が明確で読みやすいです。


特に気になるトピックがあれば、さらに詳しく説明しますよ!

Note: 216

  • ただしBFSでvisitedフラグを出てきた後に立てると急激に遅くなるケースがある

    • これは痛い目を見たことあるので、必ず入れる前にチェックする癖がついている。
    • グラフ系だと入れる前にチェックしてもコードの重複が起きないので心理的に書きやすい。
      Copied!
      while frontiers:
          node = frontiers.popleft()
          for neighbor in node.neighbors:
              if neighbor not in visited:
                  visited.add(neighbor)
                  frontiers.append(neighbor)
      

Note: 66

実装2

  • 一応、append前にNoneチェックの方法。
  • append_if_exist()みたいなヘルパー作る気も進まないのでそのまま書く。

Code: 138 ()

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root is None:
            return None
        
        stack = [root]
        while stack:
            node = stack.pop()
            node.left, node.right = node.right, node.left
            if node.left is not None:
                stack.append(node.left)
            if node.right is not None:
                stack.append(node.right)
        return root

Note: 6

Step 3

Note: 15

Note: 6

Step 4

Note: 18

自分のPR:(自分のPRへのリンク)

Prompt: 46

ここに、私が投稿したStep1-3のPRに対してレビューコメントがついています。それぞれチェックしてまとめてください。

Prompt: 25

それぞれのレビューコメントについて、もう少し詳しく教えてください。

Note: 37

実装3

  • レビューを受けて書き直し
    • (修正点)

Code: 7 ()

class Solution:
    pass

Code: 91 ()

lc_export(
    next_url="https://leetcode.com/problems/valid-anagram",
    dry_run=True,
    desc="",
    notebook_url="https://share.solve.it.com/d/9bd3c55307a8d0799a9d6b2fdeb50133"
)

Output: 4,914

=== DRY RUN: 0226-invert-binary-tree/0226-invert-binary-tree.md ===

# 226. Invert Binary Tree

- URL: https://leetcode.com/problems/invert-binary-tree/
- Difficulty: Easy
- Tags: Tree, Depth-First Search, Breadth-First Search, Binary Tree
- Notebook: https://share.solve.it.com/d/9bd3c55307a8d0799a9d6b2fdeb50133

## 問題文

<p>Given the <code>root</code> of a binary tree, invert the tree, and return <em>its root</em>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/03/14/invert1-tree.jpg" style="width: 500px; height: 165px;" />
<pre>
<strong>Input:</strong> root = [4,2,7,1,3,6,9]
<strong>Output:</strong> [4,7,2,9,6,3,1]
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/03/14/invert2-tree.jpg" style="width: 500px; height: 120px;" />
<pre>
<strong>Input:</strong> root = [2,1,3]
<strong>Output:</strong> [2,3,1]
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> root = []
<stro...

=== 17 cells would be exported ===
=== PR Title: 226. Invert Binary Tree ===
=== Notebook: https://share.solve.it.com/d/9bd3c55307a8d0799a9d6b2fdeb50133 ===
'# 226. Invert Binary Tree\n\n- URL: https://leetcode.com/problems/invert-binary-tree/\n- Difficulty: Easy\n- Tags: Tree, Depth-First Search, Breadth-First Search, Binary Tree\n- Notebook: https://share.solve.it.com/d/9bd3c55307a8d0799a9d6b2fdeb50133\n\n## 問題文\n\n<p>Given the <code>root</code> of a binary tree, invert the tree, and return <em>its root</em>.</p>\n\n<p>&nbsp;</p>\n<p><strong class="example">Example 1:</strong></p>\n<img alt="" src="https://assets.leetcode.com/uploads/2021/03/14/invert1-tree.jpg" style="width: 500px; height: 165px;" />\n<pre>\n<strong>Input:</strong> root = [4,2,7,1,3,6,9]\n<strong>Output:</strong> [4,7,2,9,6,3,1]\n</pre>\n\n<p><strong class="example">Example 2:</strong></p>\n<img alt="" src="https://assets.leetcode.com/uploads/2021/03/14/invert2-tree.jpg" style="width: 500px; height: 120px;" />\n<pre>\n<strong>Input:</strong> root = [2,1,3]\n<strong>Output:</strong> [2,3,1]\n</pre>\n\n<p><strong class="example">Example 3:</strong></p>\n\n<pre>\n<strong>Input:</strong> root = []\n<strong>Output:</strong> []\n</pre>\n\n<p>&nbsp;</p>\n<p><strong>Constraints:</strong></p>\n\n<ul>\n\t<li>The number of nodes in the tree is in the range <code>[0, 100]</code>.</li>\n\t<li><code>-100 &lt;= Node.val &lt;= 100</code></li>\n</ul>\n\n\n## Step 1\n\n### 実装1\n\n- アルゴリズムの選択\n  - 全てのノードの.leftと.rightをswapできればいい。順序はなんでもいい。\n  - preorderが最も自然なのでpreorderでやる。\n- 実装\n  - recursiveでもiterativeでもいいが、preorderはいわば末尾再帰の形なのでiterativeでも容易にかける。\n    - iterativeでやる。\n  - Noneチェックをstackにappend前にするか、pop後にするか。\n    - どっちでもいいがコード中に分散しないpop後にやる方法で書く。\n- 計算量\n  - Time: O(n)\n  - Extra Space: O(n)\n    - 実装よりここが悩んだ。\n    - Noneもappendするのでstackに最大n個入りうるのでO(n)。\n    - Noneをappend前に弾くとしたら、O(height)。height <= n/2より結局O(n)。\n\n```python\nfrom typing import Optional\n\n\n# Definition for a binary tree node.\nclass TreeNode:\n    def __init__(self, val=0, left=None, right=None):\n        self.val = val\n        self.left = left\n        self.right = right\n\n\nclass Solution:\n    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:\n        stack = [root]\n        while stack:\n            node = stack.pop()\n            if node is None:\n                continue\n            node.left, node.right = node.right, node.left\n            stack.append(node.left)\n            stack.append(node.right)\n        return root\n        \n```\n\n- 3分かかった。\n- 振り返り\n  - 書いている間、特に何も悩まなかった。\n\n## Step 2\n\n- LLMレビューの感想\n  - 特になし。\n- コメント集:空\n- PR\n  - https://github.com/ryosuketc/leetcode_grind75/pull/6\n  - https://github.com/Ryotaro25/leetcode_first60/pull/71\n  - https://github.com/huyfififi/coding-challenges/pull/6\n  - https://github.com/rihib/leetcode/pull/26/\n  - https://github.com/wf9a5m75/leetcode3/pull/13\n  - https://github.com/kzhra/Grind41/pull/6\n  - https://github.com/irohafternoon/LeetCode/pull/8\n\n**Q:** 上記に他の人が解いたPRをまとめています。それぞれのPRの学習記録とそれについているコメントをあなたがチェックし、PRごとの内容を簡潔にまとめて欲しいです。\n\n\n**A:**\n各PRの内容を確認しますね。まず全てのPRを読み込みます。\n\n各PRの内容をまとめます:\n\n---\n\n**1. ryosuketc/leetcode_grind75 PR#6** (C++)\n- **実装**: C++でiterativeとrecursive両方\n- **コメント**:\n  - `std::move`とGCについての議論 → C++にはGCがない。スタックの自動解放とGCは別物\n  - `nullptr` vs `NULL` → `nullptr`一択(`NULL`は問題を起こすことがある)\n  - 日本語個人ブログは信頼性に注意、cpprefjp等の公式リファレンスで裏取りを推奨\n\n---\n\n**2. Ryotaro25/leetcode_first60 PR#71** (C++)\n- **実装**: 再帰版とBFS版\n- **コメント**:\n  - `std::swap`を使ってswap→invertの順でも良い\n  - root == nullの早期チェックは好みの問題(統一感の議論)\n  - `using namespace std;`を避け、`std::queue`のように明示する方が実務的\n\n---\n\n**3. huyfififi/coding-challenges PR#6** (Python)\n- **実装**: DFS(stack)とBFS(queue)\n- **コメント**:\n  - stackに`None`を入れるか入れないかは好みの範囲\n  - ただしBFSでvisitedフラグを出てきた後に立てると急激に遅くなるケースがある\n  - `a, b = b, a`はPythonのイディオムとして積極的に使ってよい\n\n---\n\n**4. rihib/leetcode PR#26** (Go)\n- **実装**: 再帰版\n- **コメント**: odaさんからレビューがあったが詳細は見えず\n- ラベル: Grind75, Blind75, NeetCode150, Easy, Recursion, Stack\n\n---\n\n**5. wf9a5m75/leetcode3 PR#13** (Python)\n- **実装**: 再帰版とiterativeの複数パターン\n- **コメント**:\n  - 不要な条件分岐(`if right_tree:`等)は消せる\n  - stackに`None`を入れて出てきたらチェック、でもOK\n  - ただし`None`を入れないことでループ回数が減る(僅かだが)ので好み\n  - 「どちらでもいい」との結論\n\n---\n\n**6. kzhra/Grind41 PR#6** (C++)\n- **実装**: BFS(queue)を中心に複数パターン\n- **コメント**:\n  - 不要なelse節を削除可能\n  - `if (root->left)`のような条件なくても動く\n  - queueに全部入れてpop後にnullptrチェックする手もある\n  - nullptrなら早めに抜けてネストを浅くする提案\n\n---\n\n**7. irohafternoon/LeetCode PR#8** (C++)\n- **注意**: このPRは「Valid Parentheses」の問題で、Invert Binary Treeではありません\n- **コメント**(参考として):\n  - `using namespace std;`は名前空間を汚すので好まれない\n  - `map`に`const`修飾を付けると`[]`ではなく`at`でアクセスが必要\n  - `count`より`contains`(C++20)が明示的\n  - `emplace` vs `push`の違い(in-place構築 vs コピー/移動)\n\n---\n\n何か特定のPRについて詳しく知りたい点はありますか?\n\n- > ただしBFSでvisitedフラグを出てきた後に立てると急激に遅くなるケースがある\n  - これは痛い目を見たことあるので、必ず入れる前にチェックする癖がついている。\n  - グラフ系だと入れる前にチェックしてもコードの重複が起きないので心理的に書きやすい。\n    ```py\n    while frontiers:\n        node = frontiers.popleft()\n        for neighbor in node.neighbors:\n            if neighbor not in visited:\n                visited.add(neighbor)\n                frontiers.append(neighbor)\n    ```\n\n### 実装2\n\n- 一応、append前にNoneチェックの方法。\n- append_if_exist()みたいなヘルパー作る気も進まないのでそのまま書く。\n\n```python\nclass Solution:\n    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:\n        if root is None:\n            return None\n        \n        stack = [root]\n        while stack:\n            node = stack.pop()\n            node.left, node.right = node.right, node.left\n            if node.left is not None:\n                stack.append(node.left)\n            if node.right is not None:\n                stack.append(node.right)\n        return root\n```\n\n## Step 3\n\n[実装1](#実装1)\n\n## Step 4\n\n自分のPR:(自分のPRへのリンク)\n\n**Q:** それぞれのレビューコメントについて、もう少し詳しく教えてください。\n\n### 実装3\n\n- レビューを受けて書き直し\n  - (修正点)\n\n```python\nclass Solution:\n    pass\n```'