LeetCode--バイナリ2--木問題を解決するために再帰を使用
前のセクションでは、ツリーをトラバースする再帰的なソリューションを使用する方法を説明しました。
再帰は、問題の木を解決するための最も効果的かつ最も一般的な方法の一つです。
我々は、ツリー値と、他のノードへのポインタのリストへのポインタを含むノード(ルート)として再帰的に定義することができることを知っています。再帰は木の特徴の一つです。
そのため、多くの木問題は、再帰的にすることで解決することができます。
再帰の各レベルのために、我々は、単一ノード内の問題に焦点を当てることができ、そしてその子ノードの問題を解決するために、再帰で関数を呼び出します。
一般的に、我々は「できるトップダウン」または「ボトムアップ再帰の」木問題を解決します。
ソリューショントップダウン
「トップダウン」の各再帰レベルは、我々は最初のアクセス・ノードは、子供たちにこれらの値を渡すためにいくつかの値と再帰関数呼び出しを計算することを意味します。
前者の先行順走査とみなすことができるため、「トップダウンソリューション
:具体的には、(ルート、paramsは)TOP_DOWN再帰関数の原理は、このあります
1. return specific value for null node
2. update the answer if needed // anwer <-- params
3. left_ans = top_down(root.left, left_params) // left_params <-- root.val, params
4. right_ans = top_down(root.right, right_params) // right_params <-- root.val, params
5. return the answer if needed // answer <-- left_ans, right_ans
たとえば、この問題を考えてみます。==その最大の深さのために、一見==バイナリツリーを考えます。
私たちは、ルートノードの深さが1である知っています。
私たちはノードの深さを知っていれば、各ノードについて、我々はその子ノードの深さを知ることができます。
関数が呼び出されたときしたがって、パラメータとして渡されたノードの深さは、すべてのノードが自分の深さを認識しています。
リーフノードの場合は、私たちは深さを更新することにより、最終的な答えを得ることができます。
ここでは、再帰関数maximum_depth(根、深さ)は擬似コードです:
1. return if root is null
2. if root is a leaf node:
3. answer = max(answer, depth); // update the answer if needed
4. maximum_depth(root.left, depth + 1) // call the function recursively for left child
5. maximum_depth(root.right, depth + 1) // call the function recursively for right child
C ++コード
int answer; // don't forget to initialize answer before call maximum_depth
void maximum_depth(TreeNode* root, int depth) {
if (!root) {
return;
}
if (!root->left && !root->right) {
answer = max(answer, depth);
}
maximum_depth(root->left, depth + 1);
maximum_depth(root->right, depth + 1);
}
ボトムアップのソリューション
「ボトムアップ」は、他の再帰的な方法です。
再帰の各レベルでは、我々は最初のリターンと根自体によって答えることは価値が、その後、すべての子ノードに再帰関数を呼び出します。
このプロセスは、帰りがけ順として見ることができます。
一般的に、「ボトムアップ」再帰関数BOTTOM_UP(ルート)を次のように
1. return specific value for null node
2. left_ans = bottom_up(root.left) // call function recursively for left child
3. right_ans = bottom_up(root.right) // call function recursively for right child
4. return answers
レッツは、ツリーの最大の深さの前に問題を議論していきますが、考え方の異なる方法:
ツリーの単一ノードについて、最大深さxには、自身のサブツリーのルートがどのくらいされているノード?
我々はルートノードを知っている場合は、その左の子は、最大深さの根であるリットルであり、我々は前の質問に答えることができれば、ルートの最大の深さにその右の子は、Rのですか?
もちろん、私たちはそれらの間の最大値を選択することができ、プラス1に配置され、ツリーのサブルートの最大の深さを得ること。
すなわち、X = MAX(L、R)である + 1。
各ノードの後に答えを、私たちはその子ノードで問題を解決することができ、この手段。
したがって、我々は「ボトムアップ」を使用することができます。
以下は、再帰関数のmaximum_depth(ルート)である擬似コードです。
return 0 if root is null // return 0 for null node
2. left_depth = maximum_depth(root.left)
3. right_depth = maximum_depth(root.right)
4. return max(left_depth, right_depth) + 1 // return depth of the subtree rooted at root
C ++コード
int maximum_depth(TreeNode* root) {
if (!root) {
return 0; // return 0 for null node
}
int left_depth = maximum_depth(root->left);
int right_depth = maximum_depth(root->right);
return max(left_depth, right_depth) + 1; // return depth of the subtree rooted at root
}
バイナリツリーの最大深さ
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == NULL)
return 0;
int left_depth = maxDepth(root->left);
int right_depth = maxDepth(root->right);
return max(left_depth,right_depth)+1;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int ans = 0 ;
int maxDepth(TreeNode* root) {
int dep = 1;
helper(root , dep);
return ans;
}
void helper(TreeNode* root ,int depth)
{
if(root == NULL)
return ;
if (root->right == NULL && root->left == NULL)
ans = max(ans , depth);
if(root->right != NULL)
helper(root->right,depth+1);
if (root-> left != NULL)
helper(root->left, depth+1);
}
};
対称バイナリツリー
オリジナルのアイデアは、空想の先行順ベクトルが包括等しいかどうかを、シーケンスによって横切られます。
しかし、コードは、すべてのテストに合格しません
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
vector<int> ans;
inorder(root,ans);
int back = ans.size();
for(int i = 0; i <= back/2 ; i++)
{
cout << ans[i] << endl;
if(ans[i] != ans[back-i-1])
return false;
}
return true;
}
void inorder( TreeNode* root, vector<int> &order )
{
if(root == NULL)
{
return;
}
if (root->left != NULL){
inorder(root->left,order);
}
order.push_back(root->val);
if(root->right != NULL){
inorder(root->right,order);
}
}
};
変換のアイデア:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (root == NULL)
return true;
return helper(root->left , root->right);
}
bool helper (TreeNode* A,TreeNode* B)
{
if ( A == NULL && B == NULL)
return true;
if (A == NULL || B == NULL)
return false;
if (A->val != B->val)
return false;
return (helper(A->right,B->left)&&helper(A->left,B->right));
}
};
パスの合計
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
return helper(root,sum);
}
bool helper(TreeNode* cur, int sum)
{
if (cur == NULL)
return false;
if( cur->val == sum && cur->left == NULL && cur->right == NULL)
return true;
return (helper(cur->left , sum - cur->val) || helper(cur->right,sum - cur->val) );
}
};
ロジック:バイナリツリー内のすべてのパス、値が目標値と等しいかどうかを
- 時間が目標値かどうかを検出するために、リーフノード来たトップダウンから、