这篇博客咱们主要来看二叉树和二叉树问题中使用递归来解决问题的思路。这类问题有时思路很简单,这是由于二叉树具备自然的递归结构,因此咱们使用递归的解法解决二叉树有关的问题就变得很是明显。node
//前序遍历node节点
void preorder(TreeNode * node){
if (node == NULL){
return; //终止条件
}
cout << node -> val;
preorder(node -> left);
preorder(node -> right);//递归过程
}
复制代码
bool contain(Node *node, key key){
if (node == NULL)
return false;
if (key == node->key)
return true;
if( contain(node -> left,key) || contain(node -> right, key))
return true;
return false;
}
复制代码
void destroy(Node * node){
if(node == NULL)
return;
destroy(node->left);
destroy(node->right);
delete node;
count --;
}
复制代码
class Solution {
public:
//求节点root的深度
int maxDepth(TreeNode* root) {
//终止条件
if(root == NULL){
return 0;
}
return 1 + max(maxDepth(root -> left), maxDepth(root -> 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:
TreeNode* invertTree(TreeNode* root) {
if ( root == NULL ) {
return NULL;
}
invertTree( root->left );
invertTree( root->right );
swap ( root->left, root->right );
return root;
}
};
复制代码
有的时候递归的终止条件是存在陷阱的。ios
采起递归来解决这个问题,咱们能够从头结点开始,向它的左右孩子节点寻找sum-根节点的值,不断向下寻找。这道题陷阱在于终止条件不是node == NULL。bash
/**
* 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) {
if (root == NULL){
return false;
}
//为叶子节点
if (root -> left == NULL && root -> right == NULL){
return root -> val == sum;
}
return hasPathSum(root -> left, sum - root -> val) || hasPathSum(root -> right, sum - root -> val);
return false;
}
};
复制代码
咱们如何使用递归的返回值来解决问题。 函数的语义很重要微信
对于每个节点,就是该节点的值加上“->”再加上左子树的路径字符串和右子树路径字符串。当到达叶节点时,将字符串加入结果集。函数
/**
* 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:
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
if (root == NULL){
return res;
}
if (root -> left == NULL && root -> right == NULL){
res.push_back(to_string(root -> val));
return res;
}
vector<string> lefts = binaryTreePaths(root -> left);
for(int i = 0; i < lefts.size(); i++){
res.push_back(to_string(root -> val) + "->" + lefts[i]);
}
vector<string> rights = binaryTreePaths(root -> right);
for(int i = 0; i < rights.size(); i++){
res.push_back(to_string(root -> val) + "->" + rights[i]);
}
return res;
}
};
复制代码
猛地一看这个描述,和咱们以前的Path Sum是同样的。可是区别在于咱们对于路径的定义不必定要起始于根节点,终止于叶子结点,路径能够从任意节点开始,可是只能是向下走的。ui
在一个节点上要经过三个部分得到答案,第一个部分看看有没有一条路径,它包含node这个节点,而且它的和为sum,这个路径咱们进入findPath这个子过程,这个子过程自己又是一个递归函数。另外的两部分就是要在node的左右子树去寻找没有这个ndoe节点的值,有没有这样的路径,他们的和仍然为sum,这件事就是咱们PathSum这个函数所作的。在node->left和node->right分别调用PathSum的过程当中,他们也会调用findPath来求解。spa
#include <iostream>
using namespace std;
// 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:
// 在以root为根节点的二叉树中,寻找和为sum的路径,返回这样的路径个数
int pathSum(TreeNode* root, int sum) {
if ( root == NULL) {
return 0;
}
int res = findPath( root, sum );
res += pathSum( root->left, sum );
res += pathSum( root->right, sum );
return res;
}
private:
// 在以node为根节点的二叉树中,寻找包含node的路径,和为sum
// 返回这样的路径个数
int findPath( TreeNode* node, int num){
if ( node == NULL ) {
return 0;
}
int res = 0;
if ( node->val == num ) {
res += 1;
}
res += findPath( node->left, num - node->val );
res += findPath( node->right, num - node->val );
return res;
}
};
复制代码
二分搜索树:
每一个节点的键值大于左孩子
每一个节点的键值小于右孩子
以左右孩子为跟的子树仍为二分搜索树3d
若是咱们给的p,q节点都小于node节点,那么他们最近的公共祖先必定在node左边。若是咱们给的p,q节点都大于node节点,那么他们最近的公共祖先必定在ndoe右边。若是一小一大,那么node必定是最近的公众祖先。code
/**
* 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:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
assert(p != NULL && q != NULL);
if (root == NULL){
return NULL;
}
if ((root -> val > p -> val) && (root -> val > q -> val))
return lowestCommonAncestor(root -> left, p, q);
if ((root -> val < p -> val) && (root -> val < q -> val))
return lowestCommonAncestor(root -> right, p, q);
//p 与q在root的两侧, 则root必为公共祖先,包含p为q的祖先
return root;
}
};
复制代码
-------------------------华丽的分割线--------------------cdn
看完的朋友能够点个喜欢/关注,您的支持是对我最大的鼓励。
想了解更多,欢迎关注个人微信公众号:番茄技术小栈