-
Notifications
You must be signed in to change notification settings - Fork 0
776. Split BST #50
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
Open
Ryotaro25
wants to merge
4
commits into
main
Choose a base branch
from
problem47
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
776. Split BST #50
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /** | ||
| * 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: | ||
| vector<TreeNode*> splitBST(TreeNode* root, int target) { | ||
| TreeNode* left; | ||
| TreeNode* right; | ||
|
|
||
| splitBSTHelper(root, target, left, right); | ||
| return {left, right}; | ||
| } | ||
|
|
||
| private: | ||
| void splitBSTHelper(TreeNode* node, int target, TreeNode*& left, TreeNode*& right) { | ||
| if (!node) { | ||
| return; | ||
| } | ||
|
|
||
| if (node->val > target) { | ||
| right = node; | ||
| node = node->left; | ||
| left = nullptr; | ||
| splitBSTHelper(node, target, left, right->left); | ||
| } else { | ||
| left = node; | ||
| node = node->right; | ||
| right = nullptr; | ||
| splitBSTHelper(node, target, left->right, right); | ||
| } | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| ## ステップ1 | ||
| まず思いついたのはrootとは別に2つ新たにnodeを用意して、 | ||
| targetより小さいものと大きいものをそれぞれのツリーを作りそれらをvectorに入れて返却する。 | ||
|
|
||
| 一旦プログラムを書いて上手く動かなかったので、答えを確認し1.5hほどでacceptできた。 | ||
| 理解出来ていなかった箇所はループの小さい側、大きい側のそれぞれに2回目以降に紐付ける場合の動き。 | ||
| root = [4,2,6,1,3,5,7], target = 2の場合 | ||
| val = 4 smaller_node [] larger_node [4,6,5,7] | ||
| val = 2 smaller_node [2, 1] larger_node [4,6,5,7] | ||
| val = 3 smaller_node [2, 1] larger_node [4,3,6,5,7] // 探索終了 | ||
| ここで3をどのように大きい側に繋ぐのかは答えを確認した。 | ||
|
|
||
| 3つのnodeを使っているんのでそれぞれの値をどう更新するのか理解するのに時間がかかった。 | ||
|
|
||
| 時間計算量 | ||
| O(n) | ||
| 左右に偏っている場合 | ||
|
|
||
| 空間計算量 | ||
| O(1) | ||
|
|
||
| ## ステップ2 | ||
| ・変数名の修正 | ||
| ・理解するためにコメントを追記 | ||
| ・if文を反転 | ||
|
|
||
| 再帰でも実装recusive.cpp | ||
| 構造体を使いたかったが、返却値に合わせて型変換を行う必要があるので今回はそのまま | ||
|
|
||
| ## ステップ3 | ||
| **3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。** | ||
|
|
||
| ## 他の方の解法 | ||
| gotoさんは再帰の解法を用いている。 | ||
|
|
||
| >手作業時にいきなりプログラムありきで解き方を考えている気がする | ||
| これは自分も本当にそうでかつ、ロジックから答えを導くのではなく答えからロジックを導こうとしている。 | ||
|
|
||
| https://github.com/goto-untrapped/Arai60/pull/54/commits/570e2c2f1ee6ddcbdeaead4c40dbb2fb2a25d817 | ||
|
|
||
| 型名を決めるときの注意点 | ||
| >型は何かをできなくするための制限なので、何をできないようにしたかと、そのメリットのバランスで決めるもの | ||
|
|
||
| >分割後のtreeはleft, rightよりsmaller, largerのほうが性質の違いが表現できていていいと思った | ||
| >戻り値がleft, rightだとどっちから見てleft, rightなのかわからなくなりそうと思った | ||
| 小さい側(大きい側)のツリーにもleftとrightが存在するためsmaller largerが良さそう | ||
| https://github.com/Yoshiki-Iwasa/Arai60/pull/41 | ||
|
|
||
| >2 個連続で入れるのは、トップレベルの関数や変数の間だけが良いと思います。 | ||
| 知らなかった。 | ||
| https://github.com/Mike0121/LeetCode/pull/16 | ||
|
|
||
| ## Discordなど | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: | ||
| vector<TreeNode*> splitBST(TreeNode* node, int target) { | ||
| if (!node) { | ||
| return {nullptr, nullptr}; | ||
| } | ||
|
|
||
| if (node->val <= target) { | ||
| // 左側はtargetより小さいので右側を探索する | ||
| vector<TreeNode*> right_child = splitBST(node->right, target); | ||
| node->right = right_child[0]; | ||
| return {node, right_child[1]} | ||
| } else { | ||
| vector<TreeNode*> left_child = splitBST(node->left, target); | ||
| node->left = left_child[1]; | ||
| return {left_child[0], node} | ||
| } | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /** | ||
| * 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: | ||
| vector<TreeNode*> splitBST(TreeNode* root, int target) { | ||
| TreeNode* node = root; | ||
|
|
||
| TreeNode* smaller_head = new 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. head はリンクリストの先頭のノードを表す単語だと思います。 smaller_root はいかがでしょうか?
Owner
Author
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. @nodchip |
||
| TreeNode* smaller_node = smaller_head; | ||
|
|
||
| TreeNode* larger_head = new TreeNode(); | ||
| TreeNode* larger_node = larger_head; | ||
|
|
||
| while (node) { | ||
| if (node->val <= target) { | ||
| smaller_node->right = node; | ||
| smaller_node = smaller_node->right; | ||
| node = node->right; | ||
| smaller_node->right = nullptr; | ||
| } else { | ||
| larger_node->left = node; | ||
| larger_node = larger_node->left; | ||
| node = node->left; | ||
| larger_node->left = nullptr; | ||
| } | ||
| } | ||
|
|
||
| return {smaller_head->right, larger_head->left}; | ||
| } | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| /** | ||
| * 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: | ||
| vector<TreeNode*> splitBST(TreeNode* root, int target) { | ||
| TreeNode* node = root; | ||
|
|
||
| TreeNode* smaller_head = new TreeNode(); | ||
| TreeNode* smaller = smaller_head; | ||
|
|
||
| TreeNode* bigger_head = new TreeNode(); | ||
| TreeNode* larger = bigger_head; | ||
|
|
||
| while (node) { | ||
| if (node->val > target) { | ||
| // 現在のnodeの値の方が小さいので、 | ||
| // largerの左側に現在のnodeを紐づける | ||
| larger->left = node; | ||
| larger = larger->left; | ||
| // 小さい数字が含まれているので左側に探索を進める | ||
| node = node->left; | ||
| larger->left = nullptr; | ||
| } else { | ||
| // 現在のnodeの値の方が大きいので、 | ||
| // smallerの右側にnodeを右側に紐づける | ||
| smaller->right = node; | ||
| smaller = smaller->right; | ||
| // 大きい数字が含まれているので右側に探索を進める | ||
| node = node->right; | ||
| smaller->right = nullptr; | ||
| } | ||
| } | ||
|
|
||
| return {smaller_head->right, bigger_head->left}; | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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: | ||
| vector<TreeNode*> splitBST(TreeNode* root, int target) { | ||
| TreeNode* node = root; | ||
| TreeNode* smaller_head = new TreeNode(); | ||
| auto smaller = smaller_head; | ||
|
|
||
| TreeNode* larger_head = new TreeNode(); | ||
| auto larger = larger_head; | ||
|
|
||
| while (node) { | ||
| if (node->val > target) { | ||
| larger->left = node; | ||
| larger = larger->left; | ||
| node = node->left; | ||
| larger->left = nullptr; | ||
| } else { | ||
| smaller->right = node; | ||
| smaller = smaller->right; | ||
| node = node->right; | ||
| smaller->right = nullptr; | ||
| } | ||
| } | ||
|
|
||
| return {smaller_head->right, larger_head->left}; | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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: | ||
| vector<TreeNode*> splitBST(TreeNode* root, int target) { | ||
| TreeNode* node = root; | ||
| TreeNode* smaller_root = new TreeNode(); | ||
| auto smaller = smaller_root; | ||
|
|
||
| TreeNode* larger_root = new TreeNode(); | ||
| auto larger = larger_root; | ||
|
|
||
| while (node) { | ||
| if (node->val > target) { | ||
| larger->left = node; | ||
| larger = larger->left; | ||
| node = node->left; | ||
| larger->left = nullptr; | ||
| } else { | ||
| smaller->right = node; | ||
| smaller = smaller->right; | ||
| node = node->right; | ||
| smaller->right = nullptr; | ||
| } | ||
| } | ||
|
|
||
| return {smaller_root->right, larger_root->left}; | ||
| } | ||
| }; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
再帰とループの中間を念頭において、対応関係から相互に変換できるようにしておくといいでしょう。
一例として、中間に来るものは、このような感じです。
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.
@oda
レビューありがとうございます。またコードもありがとうございます。
こちらを元に自分でも中間のバージョンで実装してみました。
変換する作業の中でより処理が理解出来たような気がします。
一点質問ですが、TreeNode** leftや&(*left)->leftを用いる意図などあるのでしょうか?
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.
選択肢は色々です。
Google のスタイルが書き込み先はポインターというものだったのでそれに従っています。
あれ、このコード左右逆になっていますか。
Uh oh!
There was an error while loading. Please reload this page.
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.
@oda
この辺りですかね。
https://google.github.io/styleguide/cppguide.html#Inputs_and_Outputs
Google guideも何度か見返すようにします🙇♂️
このまま実行したところ左右が逆となっておりました。
node->val > targetがtrueの場合、*left = node;としておりますが
targetが現在のnodeより小さいので、
今いるNodeがleftに紐づくのではなくrightに紐づく必要があるのかと思いました。
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.
昔はアウトプットはポインターでしたが、2020年のこのあたりで変更されていますね。
google/styleguide@7a7a2f5#diff-bcadcf8be931ffdd5d6a65c60c266039cf1f96b7f35bfb772662db811214c5a0L1710
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.
@oda
1708行目あたりですねありがとうございます🙇♂️