Skip to content
Open
Show file tree
Hide file tree
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
69 changes: 69 additions & 0 deletions 226.InvertBinaryTree/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
## ステップ1
queueを使って探索し、探索中のnodeの子供をswapしていば解けそう
root = [4,2,7,1,3,6,9]で試してみる
queueに左右の順にqueueに入れることで4,2,7,1,3,6,9の順に探索できる

* node = 探索中のnode

node = 4
root = [4,7,2,6,9,1,3]

node = 2
root = [4,7,2,6,9,3,1]

node = 7
root = [4,7,2,9,6,3,1]
大丈夫そう

片側がない場合を考える
[1,2]
nullptrかどうかの判定はしないで、いれかえる
[1, null, 2]

acceptまで15分ほど
再帰でも同じことができそう

時間計算量 O(n)
空間計算量 O(n) 左右のどちらかに偏っていた場合

## ステップ2
左右のnode入れ替え部分にswapを用いる
なんとなく自分で定義していたが必要なさそう
https://en.cppreference.com/w/cpp/utility/swap.html

nullptrの判定位置を変えてみる
今回の場合どちらでも良さそう

* step2_2
再帰でも解いてみる。
inverted_leftやinverted_rightなどの一旦変数において付け替えいとエラー
=>調べてみると、直接付け替えると
node->left = invertTree(node->right);
ここで元の左側のツリー情報がなくなる。

node->right = invertTree(node->left);
元の左のnodeの情報がなくなっている.
AddressSanitizer: heap-use-after-free on addressなので解放されてしまっているのか

## ステップ3
**3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。**

## 他の方の解法
基本的な方針は同じ。
queueを使う場合のnullptrかどうかの判断タイミングは、2パターンある。
https://github.com/kzhra/Grind41/pull/6
https://github.com/wf9a5m75/leetcode3/pull/13

>大体の場合、出てきてからチェックでもいいのですが、まれに BFS で(2度入力しているかのチェックを出てきてからすると)急激に遅くなることがあります。
丸覚えてコードを書かないで意識する
https://github.com/huyfififi/coding-challenges/pull/6

root.Left, root.Right = invertTreeRecursive(root.Right), invertTreeRecursive(root.Left)
Pythonだとこの書き方できそうだけど、C++ではサポートされていない
https://github.com/rihib/leetcode/pull/26/commits/2ef461f9770746f0279814fe302af1fe8ef0b35a

## Discorなど
>細かいですが、std は standard library で C++ 誕生とともにあったのに対して、STL は standard template library という std の一部で、SGI (シリコングラフィックス)という会社が作っていたライブラリーが一部取り込まれたものです。
知らんかった。
https://github.com/irohafternoon/LeetCode/pull/8

38 changes: 38 additions & 0 deletions 226.InvertBinaryTree/step1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (!root) {
return nullptr;
}
queue<TreeNode*> traversing_nodes;
traversing_nodes.push(root);
while (!traversing_nodes.empty()) {
TreeNode* node = traversing_nodes.front();
traversing_nodes.pop();

TreeNode* temp = node->left;
node->left = node->right;
node->right = temp;

if (node->left) {
traversing_nodes.push(node->left);
}
if (node->right) {
traversing_nodes.push(node->right);
}
}

return root;
}
};
36 changes: 36 additions & 0 deletions 226.InvertBinaryTree/step2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (!root) {
return nullptr;
}
queue<TreeNode*> traversing_nodes;
traversing_nodes.push(root);
while (!traversing_nodes.empty()) {
TreeNode* node = traversing_nodes.front();
traversing_nodes.pop();

if (!node) {
continue;
}

swap(node->left, node->right);

traversing_nodes.push(node->left);
traversing_nodes.push(node->right);
}

return root;
}
};
26 changes: 26 additions & 0 deletions 226.InvertBinaryTree/step2_2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* node) {
if (!node) {
return nullptr;
}

TreeNode* inverted_left = invertTree(node->left);
Copy link

Choose a reason for hiding this comment

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

std::swap(node->left, node->right);
node->left = invertTree(node->left);
node->right = invertTree(node->right);

でもよいと思います。

Copy link
Owner Author

Choose a reason for hiding this comment

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

@nodchip
レビューありがとうございます。step2_3に追加しました。

TreeNode* inverted_right = invertTree(node->right);

node->left = inverted_right;
node->right = inverted_left;
return node;
}
};
24 changes: 24 additions & 0 deletions 226.InvertBinaryTree/step2_3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* node) {
if (!node) {
return nullptr;
}

swap(node->left, node->right);
node->left = invertTree(node->left);
node->right = invertTree(node->right);
return node;
}
};
36 changes: 36 additions & 0 deletions 226.InvertBinaryTree/step3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (!root) {

Choose a reason for hiding this comment

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

個人的には脳内フローチャートをシンプルにするために、この条件分岐は入れませんね、rootがnullの場合もline 24で回収されるので。ただ、コーナーケース?を先に回収しておく派の人もいると思うので、個人的な好みかと思います。

参考までに、関連しそうなコメントを最近見かけたので残しておきます。
https://github.com/sota009/swe-coding-practice/pull/1/files#r2079144520

Copy link
Owner Author

Choose a reason for hiding this comment

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

@huyfififi
レビューありがとうございます。いつもは先に回収してしまいたい派ですが、左右のノードは取り出した後にnullptr判定しているので統一感がなかったです。。。step4で指摘いただきました箇所は削除しました。

return nullptr;
}
queue<TreeNode*> traversing_nodes;
Copy link

@huyfififi huyfififi Jun 16, 2025

Choose a reason for hiding this comment

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

私はC++に疎いので変なことを言っている可能性が高いですが...LeetCode内でusing namespace std;が補足されているとは思いますが、#include <queue>を回答内で明示してstd::queueとした方が、実務を意識していて名前空間を汚すことに抵抗を持っていますアピールになるかもしれません。

参考までに、関連しそうなコメントが記憶の片隅にあったので置いておきます。
irohafternoon/LeetCode#8 (comment)
Google Style Guide - Namespaces

Copy link
Owner Author

Choose a reason for hiding this comment

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

@huyfififi
ありがとうございます。
コーディング面接の際には、前置きをした上でstd::等を省くつもりでした。が、練習の場ですのでつけているバージョンも書いておくべきでした。同じくstep4に追加しました。

実務ではないですがこちらの会の将棋AI開発をC++で挑戦しましたが名前空間を汚すことで何度かハマりました。。。

traversing_nodes.push(root);
while (!traversing_nodes.empty()) {
TreeNode* node = traversing_nodes.front();
traversing_nodes.pop();

if (!node) {
continue;
}

swap(node->left, node->right);

traversing_nodes.push(node->left);
traversing_nodes.push(node->right);
}

return root;
}
};
35 changes: 35 additions & 0 deletions 226.InvertBinaryTree/step4.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
#include <queue>

class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
std::queue<TreeNode*> traversing_nodes;
traversing_nodes.push(root);
while (!traversing_nodes.empty()) {
TreeNode* node = traversing_nodes.front();
traversing_nodes.pop();

if (!node) {
continue;
}

std::swap(node->left, node->right);

traversing_nodes.push(node->left);
traversing_nodes.push(node->right);
}

return root;
}
};