diff --git a/617.MergeTwoBinaryTrees/dfs.cpp b/617.MergeTwoBinaryTrees/dfs.cpp new file mode 100644 index 0000000..9ff0271 --- /dev/null +++ b/617.MergeTwoBinaryTrees/dfs.cpp @@ -0,0 +1,30 @@ +/** + * 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* mergeTrees(TreeNode* node1, TreeNode* node2) { + if (!node1 && !node2) { + return nullptr; + } + if (!node1) { + return node2; + } + if (!node2) { + return node1; + } + node1->val += node2->val; + node1->left = mergeTrees(node1->left, node2->left); + node1->right = mergeTrees(node1->right, node2->right); + + return node1; + } +}; diff --git a/617.MergeTwoBinaryTrees/memo.md b/617.MergeTwoBinaryTrees/memo.md new file mode 100644 index 0000000..5d59401 --- /dev/null +++ b/617.MergeTwoBinaryTrees/memo.md @@ -0,0 +1,44 @@ +## ステップ1 +ルール通りすごく愚直にかいた +一つ目のnodeを用いて値を足すのか、欠損しているnodeを足すのか判定を行った + +node間がoverlapしている場合つまりどちらもnullptrではに場合は、値の足し算と探索候補としてqueueに追加 +2つ目のnodeのみがnullptrでない場合は、1つ目のnodeを上書き + +上記を2つのnodeの要素(node)がなくなるまでループさせて最終的に一つ目のnodeを返却 +30分ほど掛かった +時間計算量 +O(n) + +空間計算量 +O(n) +## ステップ2 +・queueに追加するもしくは片方のnodeにmergeする部分を関数化(MergeOrPushQueue) + 2種類の作業を1つの関数で行っているのは微妙な気がする + +・MergeOrPushQueueは外側から使われないのでprivate化 + TwoNodesはメンバー関数からのみのアクセスを許可するようにprivate化 + +## 他の解法 +dfsで解くこともできる +dfs.cppに実装 +この場合も +時間計算量 +O(n) + +空間計算量 +O(n) + +新しくnodeを作る方法 +TreeNodeクラスがデストラクタをどのように定義しているのか気になるところ +左右のノードの処理は似ているので関数化出来そうだけど、可読性が下がりそうなのでやめた +左右のどちらを作業しているのかis_leftのような引数を持たせてこれの値によって処理分けを想定 + +## Discord他のPRなど +新しくnodeを作る方法もある何を持って選択肢たか意識する +>新しいのを作るか作らないのか、古い入力を壊すのか壊さないのか、共有するのかしないのか(変更しない前提ならばメモリー使用量が減る)、などのオプションがあって、自分がどれを「選択」したかを意識しましょう。 +https://github.com/fhiyo/leetcode/pull/25 +新しく作るという手段は思いついたけど、入力と分けて管理する必要性や新しくnodeを管理するコストを考えて +片方に追加していく方式にした。 + +https://github.com/nittoco/leetcode/pull/30 diff --git a/617.MergeTwoBinaryTrees/new_node.cpp b/617.MergeTwoBinaryTrees/new_node.cpp new file mode 100644 index 0000000..44993dd --- /dev/null +++ b/617.MergeTwoBinaryTrees/new_node.cpp @@ -0,0 +1,86 @@ +/** + * 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 { +private: + struct Nodes { + TreeNode* new_node; + TreeNode* first_node; + TreeNode* second_node; + }; + +public: + TreeNode* mergeTrees(TreeNode* node1, TreeNode* node2) { + if (!node1 && !node2) { + return nullptr; + } + if (!node1) { + return node2; + } + if (!node2) { + return node1; + } + + TreeNode* new_root = new TreeNode(node1->val + node2->val); + + queue search_nodes; + search_nodes.emplace(new_root, node1, node2); + + while (!search_nodes.empty()) { + const auto [current_node, first_node, second_node] = std::move(search_nodes.front()); + search_nodes.pop(); + + // 左の子ノードを処理 + TreeNode* first_left = nullptr; + TreeNode* second_left = nullptr; + if (first_node) { + first_left = first_node->left; + } + if (second_node) { + second_left = second_node->left; + } + if (first_left || second_left) { + int left_val = 0; + if (first_left) { + left_val += first_left->val; + } + if (second_left) { + left_val += second_left->val; + } + current_node->left = new TreeNode(left_val); + search_nodes.emplace(current_node->left, first_left, second_left); + } + + // 右の子ノードを処理 + TreeNode* first_right = nullptr; + TreeNode* second_right = nullptr; + if (first_node) { + first_right = first_node->right; + } + if (second_node) { + second_right = second_node->right; + } + if (first_right || second_right) { + int right_val = 0; + if (first_right) { + right_val += first_right->val; + } + if (second_right) { + right_val += second_right->val; + } + current_node->right = new TreeNode(right_val); + search_nodes.emplace(current_node->right, first_right, second_right); + } + } + + return new_root; + } +}; diff --git a/617.MergeTwoBinaryTrees/new_node_step2.cpp b/617.MergeTwoBinaryTrees/new_node_step2.cpp new file mode 100644 index 0000000..8af6eb0 --- /dev/null +++ b/617.MergeTwoBinaryTrees/new_node_step2.cpp @@ -0,0 +1,73 @@ +/** + * 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* mergeTrees(TreeNode* node1, TreeNode* node2) { + TreeNode* new_root = new TreeNode(); + queue search_nodes; + search_nodes.emplace(new_root, node1, node2); + + while (!search_nodes.empty()) { + auto [current_node, left_child, right_child] = search_nodes.front(); + search_nodes.pop(); + if (!left_child && !right_child) { + return nullptr; + } + + int current_val = 0; + if (left_child) { + current_val += left_child->val; + } + if (right_child) { + current_val += right_child->val; + } + current_node->val = current_val; + + // 左の子ノードを処理 + TreeNode* left_first = nullptr; + if (left_child && left_child->left) { + left_first = left_child->left; + } + TreeNode* left_second = nullptr; + if (right_child && right_child->left) { + left_second = right_child->left; + } + if (left_first || left_second) { + current_node->left = new TreeNode(); + search_nodes.emplace(current_node->left, left_first, left_second); + } + + // 右の子ノードを処理 + TreeNode* right_first = nullptr; + if (left_child && left_child->right) { + right_first = left_child->right; + } + TreeNode* right_second = nullptr; + if (right_child && right_child->right) { + right_second = right_child->right; + } + if (right_first || right_second) { + current_node->right = new TreeNode(); + search_nodes.emplace(current_node->right, right_first, right_second); + } + } + + return new_root; + } + +private: + struct Nodes { + TreeNode* node; + TreeNode* left_child; + TreeNode* right_child; + }; +}; diff --git a/617.MergeTwoBinaryTrees/new_node_step3.cpp b/617.MergeTwoBinaryTrees/new_node_step3.cpp new file mode 100644 index 0000000..7ebe7d1 --- /dev/null +++ b/617.MergeTwoBinaryTrees/new_node_step3.cpp @@ -0,0 +1,73 @@ +/** + * 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* mergeTrees(TreeNode* node1, TreeNode* node2) { + if (!node1 && !node2) { + return nullptr; + } + TreeNode* new_root = new TreeNode(); + queue search_nodes; + search_nodes.push({new_root, node1, node2}); + + while (!search_nodes.empty()) { + auto [current_node, first_node, second_node] = search_nodes.front(); + search_nodes.pop(); + + int current_val = 0; + if (first_node) { + current_val += first_node->val; + } + if (second_node) { + current_val += second_node->val; + } + current_node->val = current_val; + + // 左の子ノードを処理 + TreeNode* first_left = nullptr; + if (first_node) { + first_left = first_node->left; + } + TreeNode* second_left = nullptr; + if (second_node) { + second_left = second_node->left; + } + if (first_left || second_left) { + current_node->left = new TreeNode(); + search_nodes.emplace(current_node->left, first_left, second_left); + } + + // 右の子ノードを処理 + TreeNode* first_right = nullptr; + if (first_node) { + first_right = first_node->right; + } + TreeNode* second_right = nullptr; + if (second_node) { + second_right = second_node->right; + } + if (first_right || second_right) { + current_node->right = new TreeNode(); + search_nodes.push({current_node->right, first_right, second_right}); + } + } + + return new_root; + } + +private: + struct MergedAndOriginalNodes { + TreeNode* node; + TreeNode* left_child; + TreeNode* right_child; + }; +}; diff --git a/617.MergeTwoBinaryTrees/step1.cpp b/617.MergeTwoBinaryTrees/step1.cpp new file mode 100644 index 0000000..c54d2f6 --- /dev/null +++ b/617.MergeTwoBinaryTrees/step1.cpp @@ -0,0 +1,53 @@ +/** + * 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: + struct TwoNodes { + TreeNode* first_node; + TreeNode* second_node; + }; + + TreeNode* mergeTrees(TreeNode* node1, TreeNode* node2) { + if (!node1 && !node2) { + return nullptr; + } + if (!node1) { + return node2; + } + if (!node2) { + return node1; + } + + queue search_nodes; + search_nodes.emplace(node1, node2); + while (!search_nodes.empty()) { + auto [first_node, second_node] = std::move(search_nodes.front()); + search_nodes.pop(); + + first_node->val += second_node->val; + + if (first_node->left && second_node->left) { + search_nodes.emplace(first_node->left, second_node->left); + } else if (second_node->left) { + first_node->left = second_node->left; + } + + if (first_node->right && second_node->right) { + search_nodes.emplace(first_node->right, second_node->right); + } else if (second_node->right) { + first_node->right = second_node->right; + } + } + + return node1; + } +}; diff --git a/617.MergeTwoBinaryTrees/step2.cpp b/617.MergeTwoBinaryTrees/step2.cpp new file mode 100644 index 0000000..b8cd7e6 --- /dev/null +++ b/617.MergeTwoBinaryTrees/step2.cpp @@ -0,0 +1,53 @@ +/** + * 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 { +private: + struct TwoNodes { + TreeNode* first_node; + TreeNode* second_node; + }; + + void MergeOrPushQueue(queue &search_nodes, TreeNode*& first_node, TreeNode*& second_node) { + if (first_node && second_node) { + search_nodes.emplace(first_node, second_node); + } else if (second_node) { + first_node = second_node; + } + } + +public: + TreeNode* mergeTrees(TreeNode* node1, TreeNode* node2) { + if (!node1 && !node2) { + return nullptr; + } + if (!node1) { + return node2; + } + if (!node2) { + return node1; + } + + queue search_nodes; + search_nodes.emplace(node1, node2); + while (!search_nodes.empty()) { + auto [first_node, second_node] = std::move(search_nodes.front()); + search_nodes.pop(); + + first_node->val += second_node->val; + + MergeOrPushQueue(search_nodes, first_node->left, second_node->left); + MergeOrPushQueue(search_nodes, first_node->right, second_node->right); + } + + return node1; + } +}; diff --git a/617.MergeTwoBinaryTrees/step3.cpp b/617.MergeTwoBinaryTrees/step3.cpp new file mode 100644 index 0000000..b8cd7e6 --- /dev/null +++ b/617.MergeTwoBinaryTrees/step3.cpp @@ -0,0 +1,53 @@ +/** + * 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 { +private: + struct TwoNodes { + TreeNode* first_node; + TreeNode* second_node; + }; + + void MergeOrPushQueue(queue &search_nodes, TreeNode*& first_node, TreeNode*& second_node) { + if (first_node && second_node) { + search_nodes.emplace(first_node, second_node); + } else if (second_node) { + first_node = second_node; + } + } + +public: + TreeNode* mergeTrees(TreeNode* node1, TreeNode* node2) { + if (!node1 && !node2) { + return nullptr; + } + if (!node1) { + return node2; + } + if (!node2) { + return node1; + } + + queue search_nodes; + search_nodes.emplace(node1, node2); + while (!search_nodes.empty()) { + auto [first_node, second_node] = std::move(search_nodes.front()); + search_nodes.pop(); + + first_node->val += second_node->val; + + MergeOrPushQueue(search_nodes, first_node->left, second_node->left); + MergeOrPushQueue(search_nodes, first_node->right, second_node->right); + } + + return node1; + } +}; diff --git a/617.MergeTwoBinaryTrees/step4.cpp b/617.MergeTwoBinaryTrees/step4.cpp new file mode 100644 index 0000000..341e9b0 --- /dev/null +++ b/617.MergeTwoBinaryTrees/step4.cpp @@ -0,0 +1,53 @@ +/** + * 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 { +private: + struct TwoNodes { + TreeNode* first_node; + TreeNode* second_node; + }; + + void MergeOrPushQueue(queue &search_nodes, TreeNode*& first_node, TreeNode* const second_node) { + if (first_node && second_node) { + search_nodes.emplace(first_node, second_node); + } else if (second_node) { + first_node = second_node; + } + } + +public: + TreeNode* mergeTrees(TreeNode* node1, TreeNode* node2) { + if (!node1 && !node2) { + return nullptr; + } + if (!node1) { + return node2; + } + if (!node2) { + return node1; + } + + queue search_nodes; + search_nodes.emplace(node1, node2); + while (!search_nodes.empty()) { + auto [first_node, second_node] = std::move(search_nodes.front()); + search_nodes.pop(); + + first_node->val += second_node->val; + + MergeOrPushQueue(search_nodes, first_node->left, second_node->left); + MergeOrPushQueue(search_nodes, first_node->right, second_node->right); + } + + return node1; + } +}; diff --git a/617.MergeTwoBinaryTrees/step5.cpp b/617.MergeTwoBinaryTrees/step5.cpp new file mode 100644 index 0000000..c28e2a2 --- /dev/null +++ b/617.MergeTwoBinaryTrees/step5.cpp @@ -0,0 +1,47 @@ +/** + * 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* mergeTrees(TreeNode* root1, TreeNode* root2) { + if (!root1 && !root2) { + return nullptr; + } + if (!root1) { + return root2; + } + if (!root2) { + return root1; + } + queue> node_pairs; + node_pairs.push({root1, root2}); + while (!node_pairs.empty()) { + auto [node1, node2] = node_pairs.front(); + node_pairs.pop(); + + if (!node1 || !node2) { + continue; + } + node1->val += node2->val; + if (!node1->left) { + node1->left = node2->left; + } else { + node_pairs.push({node1->left, node2->left}); + } + if (!node1->right) { + node1->right = node2->right; + } else { + node_pairs.push({node1->right, node2->right}); + } + } + return root1; + } +};