diff --git a/776/776.md b/776/776.md new file mode 100644 index 0000000..d210ffe --- /dev/null +++ b/776/776.md @@ -0,0 +1,110 @@ +一応ここに書いたコードはすべてLLMに聞いて期待通りに動作するだろうとは言われたコードですが、LeetCodeなどで試せているわけではないのでもしかしたら動かないかもしれないです。動かないと思ったら教えてください。 + +## 何も見ずに解いてみる + +```cpp +class Solution { +public: + vector splitBST(TreeNode* root, int target) { + if (root == nullptr) { + return {nullptr, nullptr}; + } + if (root->val <= target) { + vector right_split = splitBST(root->right, target); + TreeNode* lesser_root_of_right = right_split[0]; + TreeNode* greater_root_of_right = right_split[1]; + root->right = lesser_root_of_right; + return {root, greater_root_of_right}; + } + else { + vector left_split = splitBST(root->left, target); + TreeNode* lesser_root_of_left = left_split[0]; + TreeNode* greater_root_of_left = left_split[1]; + root->left = greater_root_of_left; + return {lesser_root_of_left, root}; + } + } +}; +``` + +## 他の人のコードを見てみる + +https://github.com/Ryotaro25/leetcode_first60/pull/50/files +https://github.com/Mike0121/LeetCode/pull/16/files +https://github.com/tokuhirat/LeetCode/pull/47/files + +最初見たときループ版が何をやっているのかあまりわからなかったがしばらく考えているとなんとなく分かった。 +ループ版も書いてみる。 + +```cpp +class Solution { +public: + vector splitBST(TreeNode* root, int target) { + TreeNode* lesser_root = nullptr; + TreeNode* greater_root = nullptr; + TreeNode** lesser_subtree_root_to_fill = &lesser_root; + TreeNode** greater_subtree_root_to_fill = &greater_root; + TreeNode* node = root; + while (node) { + if (node->val <= target) { + *lesser_subtree_root_to_fill = node; + TreeNode* tmp = node->right; + node->right = nullptr; + lesser_subtree_root_to_fill = &node->right; + node = tmp; + } + else { + *greater_subtree_root_to_fill = node; + TreeNode* tmp = node->left; + node->left = nullptr; + greater_subtree_root_to_fill = &node->left; + node = tmp; + } + } + return {lesser_root, greater_root}; + } +}; +``` + +変数名の組み合わせはsmaller, greaterとすると対称的過ぎてx < target, x > targetみたいな印象になる気がする(x <= target, x > targetではなく) +ただ別にlesserでもその印象はそんなに変わらないかも・・・ + +再帰でやると全部のノードについて関数を呼び出さなきゃいけないので時間計算量がO(N)になるが、ループだと必要なポインタだけ変えていくので階層分で済んで(バランスされた木なら)O(logN)になる。 +(再帰でも空間計算量はO(logN)かな?) + +あと、番兵をnewで作るときは関数を終わるときにdeleteしないとメモリーリークになってしまうっぽい。 +ただ、`TreeNode lesser_bst_node()`みたいな感じで作ればスコープを抜けたときに自動で解放されるらしい。 + +関数の返り値は本当はstd::pairとかにしたい気がする。 + +## 最終コード + +```cpp +class Solution { +public: + vector splitBST(TreeNode* root, int target) { + TreeNode* lesser_root = nullptr; + TreeNode* greater_root = nullptr; + TreeNode** lesser_subtree_root_to_find = &lesser_root; + TreeNode** greater_subtree_root_to_find = &greater_root; + TreeNode* node = root; + while (node) { + if (node->val <= target) { + *lesser_subtree_root_to_find = node; + TreeNode* tmp = node->right; + node->right = nullptr; + lesser_subtree_root_to_find = &node->right; + node = tmp; + } + else { + *greater_subtree_root_to_find = node; + TreeNode* tmp = node->left; + node->left = nullptr; + greater_subtree_root_to_find = &node->left; + node = tmp; + } + } + return {lesser_root, greater_root}; + } +}; +```