-
Notifications
You must be signed in to change notification settings - Fork 0
617. Merge Two Binary Trees #26
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// 自力解法。10分くらいでAC | ||
// 時間計算量: O(n) n:2つの木の要素数、空間計算量: O(n) | ||
// 左の木と右の木について処理はほぼ一緒なので関数化したかったが、left, rightが微妙に厄介で思いつかなかった。 | ||
public class solution1_1 { | ||
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { | ||
if (root1 == null && root2 == null) { | ||
return null; | ||
} | ||
int r1Value = root1 != null ? root1.val : 0; | ||
int l1Value = root2 != null ? root2.val : 0; | ||
TreeNode mergedNode = new TreeNode(r1Value + l1Value); | ||
|
||
if (root1 == null) { | ||
mergedNode.left = root2.left; | ||
} else if (root2 == null) { | ||
mergedNode.left = root1.left; | ||
} else { | ||
mergedNode.left = mergeTrees(root1.left, root2.left); | ||
} | ||
if (root1 == null) { | ||
mergedNode.right = root2.right; | ||
} else if (root2 == null) { | ||
mergedNode.right = root1.right; | ||
} else { | ||
mergedNode.right = mergeTrees(root1.right, root2.right); | ||
} | ||
return mergedNode; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* LeetCodeの解法を参考にしたもの。 計算量はsolution1_1と変わりなし。 | ||
* 対象がnullだったら別の方を返すだけでよく、両方ある時は値を合算して、再帰するだけでいいというものだった。自力解法のときに再帰した時にどうなるかをイメージが甘かったなと気付かされた。 | ||
*/ | ||
public class solution2_1 { | ||
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { | ||
if (root1 == null) { | ||
return root2; | ||
} | ||
if (root2 == null) { | ||
return root1; | ||
} | ||
TreeNode mergedTree = new TreeNode(root1.val + root2.val); | ||
mergedTree.left = mergeTrees(root1.left, root2.left); | ||
mergedTree.right = mergeTrees(root1.right, root2.right); | ||
return mergedTree; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/** | ||
* solution2_1についてhttps://github.com/colorbox/leetcode/pull/37/filesのコメントにあった、入力の木と出力の木で共有されている場合があることに備えて、すべて新しい木を生成しなおしたもの | ||
* * | ||
*/ | ||
public class solution2_2 { | ||
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { | ||
if (root1 == null && root2 == null) { | ||
return null; | ||
} else if (root1 == null) { | ||
return makeOneChildTree(root2); | ||
} else if (root2 == null) { | ||
return makeOneChildTree(root1); | ||
} | ||
TreeNode mergedTree = new TreeNode(root1.val + root2.val); | ||
mergedTree.left = mergeTrees(root1.left, root2.left); | ||
mergedTree.right = mergeTrees(root1.right, root2.right); | ||
return mergedTree; | ||
} | ||
|
||
private TreeNode makeOneChildTree(TreeNode child) { | ||
TreeNode tree = new TreeNode(child.val); | ||
tree.left = mergeTrees(null, child.left); | ||
tree.right = mergeTrees(null, child.right); | ||
return tree; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/** | ||
* https://github.com/seal-azarashi/leetcode/pull/22/filesなどを参考にStackを用いたDFS | ||
* 左と右でほぼ同様の処理をしているが、うまく関数として切り出せなかった。。 | ||
* 実装中に恥ずかしながら左右木が両方nullのときは、mergeをnullにするだけでいいと誤認していたが、mergeをnullにしても、その親の木からの参照はnullにならずに悩んだ。 | ||
* 変数mergeをnullにしてもmergeの参照先がnullになるだけで、親の木がみている元々の参照は残り続けるから→特にNode系を扱う時は参照がどうなっているのかをしっかり意識したい。 | ||
*/ | ||
public class solution2_3 { | ||
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { | ||
|
||
if (root1 == null && root2 == null) { | ||
return null; | ||
} | ||
// 配列でやってるが、構造体を用意してもいい。 | ||
Stack<TreeNode[]> nodesForMerge = new Stack<>(); | ||
TreeNode mergedTree = new TreeNode(); | ||
if (root1 == null) { | ||
mergedTree.val = root2.val; | ||
} else if (root2 == null) { | ||
mergedTree.val = root1.val; | ||
} else { | ||
mergedTree.val = root1.val + root2.val; | ||
} | ||
Comment on lines
+16
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. root1があったらroot1.valを加算 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます!条件分と処理が反転するよりそちらのがたしかに直感的でわかりやすいですね! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. あとから気づいたんですが、最初のこの処理はwhileでの処理と重複するのでいらなそうですね、、、 |
||
nodesForMerge.push(new TreeNode[] {mergedTree, root1, root2}); | ||
|
||
while (!nodesForMerge.isEmpty()) { | ||
TreeNode[] nodes = nodesForMerge.pop(); | ||
TreeNode merge = nodes[0]; | ||
TreeNode left = nodes[1]; | ||
TreeNode right = nodes[2]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. left,rightがTreeNodeのメンバとおなじ名前で強めの違和感を感じました。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます!おっしゃるとおり読み返してもわかりにくいのでそちらのleft,rightはやめようとおもいます |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 少し場合分けが多いですね。番兵を使うのは一つでしょう。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます!番兵つかったら、処理をかなり簡略化できました!番兵をつかうという意識にまだなれていないので、整理してつかえるようにしようと思います |
||
TreeNode nextMergedLeftNode = new TreeNode(); | ||
if (left == null) { | ||
merge.val = right.val; | ||
if (right.left != null) { | ||
merge.left = nextMergedLeftNode; | ||
nodesForMerge.push(new TreeNode[] {nextMergedLeftNode, null, right.left}); | ||
} | ||
} else if (right == null) { | ||
merge.val = left.val; | ||
if (left.left != null) { | ||
merge.left = nextMergedLeftNode; | ||
nodesForMerge.push(new TreeNode[] {nextMergedLeftNode, left.left, null}); | ||
} | ||
} else { | ||
merge.val = left.val + right.val; | ||
if (left.left != null || right.left != null) { | ||
merge.left = nextMergedLeftNode; | ||
nodesForMerge.push(new TreeNode[] {nextMergedLeftNode, left.left, right.left}); | ||
} | ||
} | ||
Comment on lines
+32
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rightが存在するときはmerge.valにright.valを加算、 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます! |
||
|
||
TreeNode nextMergedRightNode = new TreeNode(); | ||
if (left == null) { | ||
merge.val = right.val; | ||
if (right.right != null) { | ||
nodesForMerge.push(new TreeNode[] {nextMergedRightNode, null, right.right}); | ||
merge.right = nextMergedRightNode; | ||
} | ||
} else if (right == null) { | ||
merge.val = left.val; | ||
if (left.right != null) { | ||
nodesForMerge.push(new TreeNode[] {nextMergedRightNode, left.right, null}); | ||
merge.right = nextMergedRightNode; | ||
} | ||
} else { | ||
merge.val = left.val + right.val; | ||
if (left.right != null || right.right != null) { | ||
nodesForMerge.push(new TreeNode[] {nextMergedRightNode, left.right, right.right}); | ||
merge.right = nextMergedRightNode; | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 具体的な解決案を示せず申し訳ないのですが There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます!上記のコメントでいただいた番兵をつかうとかなり繰り返しをけせました! |
||
} | ||
return mergedTree; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* いただいたコメントを元に修正したもの。 具体的には番兵を使った分岐処理の削除、変数名の変更、Stackに追加する構造体の定義を行なった。 | ||
* 番兵については、連結リストでつかったり、ループでも使える場面もあるので条件分岐が大きくなったら番兵で減らせないかを考える癖をつける | ||
*/ | ||
public class solution3_1 { | ||
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { | ||
if (root1 == null && root2 == null) { | ||
return null; | ||
} | ||
Stack<TreeForMerge> nodesForMerge = new Stack<>(); | ||
TreeNode mergedTree = new TreeNode(); | ||
nodesForMerge.push(new TreeForMerge(mergedTree, root1, root2)); | ||
while (!nodesForMerge.isEmpty()) { | ||
TreeForMerge nodes = nodesForMerge.pop(); | ||
TreeNode merge = nodes.merge; | ||
if (nodes.node1 == null && nodes.node2 == null) { | ||
continue; | ||
} | ||
TreeNode node1 = nodes.node1 != null ? nodes.node1 : new TreeNode(0); | ||
TreeNode node2 = nodes.node2 != null ? nodes.node2 : new TreeNode(0); | ||
merge.val = node1.val + node2.val; | ||
|
||
if (node1.left != null || node2.left != null) { | ||
TreeNode leftNode = new TreeNode(); | ||
merge.left = leftNode; | ||
nodesForMerge.push(new TreeForMerge(leftNode, node1.left, node2.left)); | ||
} | ||
if (node1.right != null || node2.right != null) { | ||
TreeNode rightNode = new TreeNode(); | ||
merge.right = rightNode; | ||
nodesForMerge.push(new TreeForMerge(rightNode, node1.right, node2.right)); | ||
} | ||
} | ||
return mergedTree; | ||
} | ||
|
||
record TreeForMerge(TreeNode merge, TreeNode node1, TreeNode node2) {} | ||
; | ||
} |
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.
Java の場合、定義するほうが趣味ですね。同じものが繰り返されているわけではないので。
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.
ありがとうございます!定義する方が明示的ですしそちらを意識するようにします