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
50 changes: 50 additions & 0 deletions 779/solution1_1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
・概要
自力解法。
テストケースの洗い出しが足りず、そもそも求められているものと違うことに気づくが、解法がわからずACできず。
15分くらい

*/

import javax.swing.tree.TreeNode;

public class solution1_1 {
public TreeNode[] splitBST(TreeNode root, int target) {
if (root.val == target) {
return new TreeNode[] {root, null};
}
return new TreeNode[] {getTargetTreeAndChangeSubTree(root, target), root};
}

private TreeNode getTargetTreeAndChangeSubTree(TreeNode current, int target) {
if (current == null) {
return null;
}
if (target < current.val) {
if (current.left == null) {
return null;
}
if (current.left.val == target) {
TreeNode subTree = current.left;
current.left = current.left.right;
subTree.right = null;
return subTree;
} else {
return getTargetTreeAndChangeSubTree(current.left, target);
}
} else {
if (current.right == null) {
return null;
}
if (current.right.val == target) {
TreeNode subTree = current.right;

current.right = current.right.left;
subTree.left = null;
return subTree;
} else {
return getTargetTreeAndChangeSubTree(current.right, target);
}
}
}
}
45 changes: 45 additions & 0 deletions 779/solution2_1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
・概要
LeetCodeの解説や他の人の解法をみた。
https://github.com/Ryotaro25/leetcode_first60/pull/50/files

・解法
この問題では、元の木構造を保ちながら、target以下の値だけの木と、targetより大きい値の木に分けるという内容である。
solution1_1で直感的にできそうだが、
8
3 9
4
5
みたいな木でtargetが5のときに対応できない。
ということで根から各々木を降りながらみていく。各再帰で返す値は、その時点でのtarget以下の木とtargetより大きいだけの木である。
木の値がtarget以下であれば、左の部分木はBSTなのですべてその木の値以下なので構造を変える必要がない。逆に右の部分木はまだTarget以下の木がある可能性があるので、再帰で見る必要がある。
再帰でかえされる二つの木の内、target以下の木については、現在の値よりは大きいはず(元々自身の右の部分木の一部なので)なので、右の部分木にする。
木の値がtargetより大きい値であれば、先ほどと同様の動きで左の部分木をみていく。

・計算量
O(h): 木の深さ

・所感
簡単なテストケースのみで問題の本質を誤認してしまった。またBSTの内容を理解していれば、単純に親との関係を見るだけではダメなことは気付けだはず。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

紙と鉛筆で絵を書く、くらいですかねえ……。

本質的な原因はテストケースの洗い出しが適当だったこと、LeetCodeのテストサンプルだけを鵜呑みにしたことが原因なので、
https://github.com/goto-untrapped/Arai60/pull/54/files
にあるとおり、シンプルケース→もうすこし難しいケース→エッジケースの流れの洗い出しを必ずするようにする(まだ仕事での取り組み方とLeetCodeでの問題のやり方を分離していてよくない。)

*/

public class solution2_1 {
public TreeNode[] splitBST(TreeNode root, int target) {
if (root == null) {
return new TreeNode[2];
}
if (target < root.val) {
TreeNode[] small = splitBST(root.left, target);
root.left = leftSubTree[1];
return new TreeNode[] {leftSubTree[0], root};
} else {
TreeNode[] rightSubTree = splitBST(root.right, target);
root.right = rightSubTree[0];
return new TreeNode[] {root, rightSubTree[1]};
}
}
}
42 changes: 42 additions & 0 deletions 779/solution2_2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
・概要
LeetCodeの解説や他の人の解法を見たもの
https://github.com/Ryotaro25/leetcode_first60/pull/50/files#diff-776c4af48e8dabf508f652032b95d33f3ef8308547e1fdd2dc55e447d6bc1af8R26

自分の言葉で頭を整理する。

・解法
再帰を使わずに繰り返し処理で実装したもの
考え方は再帰と一緒だが、再帰のbottomupと違って、根から順々に処理していくので、上から順に木を繋げていく。
繰り返し処理の部分は、再帰と一緒で現在の木の値がtarget以下かどうかで処理を分ける。
現在見ている木の値がtarget以下の時は、target以下の木に繋げていく。現在のtarget以下の木の現在みているものをXとする。ここで気になるのはXの左右のどちらに繋ぐかということだが、
Xの左の部分木は必ずtarget以下となっていて、そもそも探索する必要がないので探索してXに繋ぐ可能性があるのはXの右の部分木に含まれる木であり、つまりXより大きい値なのでXの右に繋ぐしかない。
上記である通り、次に探索するのは現在の木の右の部分木となる。
またこのときtarget以下の木についても現在の木に更新し、かつその木の右の部分木はtargetより大きい可能性もあるのでnullにする。
現在見ている木の値がtarget以上の時も、上記と同様に行なっていく
*/

public class solution2_2 {
public TreeNode[] splitBST(TreeNode root, int target) {
TreeNode current = root;
TreeNode smallDummy = new TreeNode(0);
TreeNode largeDummy = new TreeNode(0);
TreeNode smallTail = smallDummy;
TreeNode largeTail = largeDummy;

while (current != null) {
if (current.val <= target) {
smallTail.right = current;
smallTail = current;
current = current.right;
smallTail.right = null;
} else {
largeTail.left = current;
largeTail = current;
current = current.left;
largeTail.left = null;
}
}
return new TreeNode[] {smallDummy.right, largeDummy.left};
}
}