二叉树的递归套路

思路:以X为根的树怎么得到结果,然后讨论可能性,需要哪些信息,然后创建信息类
模板:获取左子树的信息,获取右子树的信息,然后得到自己的信息
110. 平衡二叉树

平衡二叉树:左子树为平衡二叉树,右子树为平衡二叉树,左右子树高度差绝对值小于等于1
当判断以X为根的树是否为平衡二叉树时,需要三类信息,就是以上所列的,因此可以额外设计一个类,保存三类信息
class Info{
public:
bool isBlance;
int height;
Info(bool isBlance,int height):isBlance(isBlance),height(height){}
};

/**
 * 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:
    class Info{
    public:
        bool isBlance;
        int height;
        Info(bool isBlance,int height):isBlance(isBlance),height(height){}
    };
    Info* process(TreeNode* root){
        if(root==nullptr){//空树是平衡二叉树
            return new Info(true,0);
        }
        Info* leftInfo=process(root->left);
        Info* rightInfo=process(root->right);
        bool isBlance=true;//以root为根结点的树
        //满足下面3个if条件的任何一个,则该树就是平衡二叉树
        if(!leftInfo->isBlance){
            isBlance=false;
        }   
        if(!rightInfo->isBlance){
            isBlance=false;
        }
        if(abs(leftInfo->height - rightInfo->height)>1){
            isBlance=false;
        }
        int height=max(leftInfo->height,rightInfo->height)+1;//该树的高度
        return new Info(isBlance,height);
    }
    bool isBalanced(TreeNode* root) {
        return process(root)->isBlance;
    }
};

98. 验证二叉搜索树

分析:二叉搜索树的判断逻辑:

  1. 左子树为二叉搜索树
  2. 右子树为二叉搜索树
  3. 根节点的值大于左子树的最大值
  4. 根节点的值下于右子树的最小值
    满足以上条件的就是二叉搜索树。所以需要知道左右子树的相关信息
    class Info{
    public:
    bool isSearch;
    int maxVal;
    int minVal;
    Info(bool isSearch,int maxVal,int minVal):isSearch(isSearch),maxVal(maxVal),minVal(minVal){}
    };
    就是用来保存左右子树的相关信息
/**
 * 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:
    class Info{
    public:
        bool isSearch;
        int maxVal;
        int minVal;
        Info(bool isSearch,int maxVal,int minVal):isSearch(isSearch),maxVal(maxVal),minVal(minVal){}
    };
    Info* process(TreeNode* root){
        if(root==nullptr){//空树直接返回空
            return nullptr;
        }
        Info* leftInfo=process(root->left);//获得左子树的相关信息
        Info* rightInfo=process(root->right);//获得右子树的相关信息
        bool isSearch=true;
        int maxVal=root->val;
        int minVal=root->val;
        //判断逻辑
        if(leftInfo!=nullptr && !leftInfo->isSearch){
            isSearch=false;
        }
        if(rightInfo!=nullptr && !rightInfo->isSearch){
            isSearch=false;
        }
        if(leftInfo!=nullptr && root->val<=leftInfo->maxVal){
            isSearch=false;
        }
        if(rightInfo!=nullptr && root->val>=rightInfo->minVal){
            isSearch=false;
        }
        //求本树的最大值和最小值
        if(leftInfo!=nullptr && leftInfo->maxVal>maxVal){
            maxVal=leftInfo->maxVal;
        }
        if(rightInfo!=nullptr && rightInfo->maxVal>maxVal){
            maxVal=rightInfo->maxVal;
        }
        if(leftInfo!=nullptr && leftInfo->minVal<minVal){
            minVal=leftInfo->minVal;
        }
        if(rightInfo!=nullptr && rightInfo->minVal<minVal){
            minVal=rightInfo->minVal;
        }
        return new Info(isSearch,maxVal,minVal);

    }
    bool isValidBST(TreeNode* root) {
        return process(root)->isSearch;
    }
};

求二叉树的最大距离,即路径的最大节点数

分析:假设要求以X节点为根的树的最大距离。
有三种情况:

  1. 最大距离在左子树上
  2. 最大距离在右子树上
  3. 最大距离经过X节点,即左子树的高度+右子树的高度+1
    所以本题需要知道左子树的相关信息和右子树的相关信息
    因此需要构建Info类
    class Info {
    public:
    int largestDis;//最大距离
    int height;//高度
    Info(int largestDis,int height):largestDis(largestDis),height(height){}
    };
Info* process(Node* root) {//返回以root为根的树的相关信息
    if (root == NULL) {
        return new Info(0, 0);
    }
    Info* leftInfo = process(root->left);
    Info* rightInfo = process(root->right);
    //三种可能性
    int p1 = leftInfo->largestDis;
    int p2 = rightInfo->largestDis;
    int p3 = leftInfo->height + rightInfo->height + 1;
    int height = max(leftInfo->height, rightInfo->height) + 1;
    return new Info(max(p1, p2, p3), height);
}
int largetDis(Node* root) {
    process(root)->largestDis;
}

判断一棵树是否为满二叉树

分析:假设判断以X为根的二叉树是否为满二叉树
如果二叉树的节点数等于2h -1,(h为二叉树的高度),则该树为满二叉树。
要得到二叉树的节点数,需要知道左子树的节点数和右子树的节点数
要得到二叉树的高度,需要知道左子树的高度和右子树的高度。
所以信息类Info
class Info {
public:
int nodeSum;
int height;
Info(int nodeSum,int height):nodeSum(nodeSum),height(height){}
};

Info* process(Node* root) {
    if (root == NULL) {
        return new Info(0, 0);
    }
    Info* leftInfo = process(root->left);
    Info* rightInfo = process(root->right);
    int nodeSum = leftInfo->nodeSum + rightInfo->nodeSum + 1;
    int height = max(leftInfo->height, rightInfo->height) + 1;
    return new Info(nodeSum, height);
}
bool isFullBinaryTree(Node* root) {
    int height = process(root)->height;
    int nodeSum = process(root)->nodeSum;
    return nodeSum == pow(2, height) - 1;
}

二叉树中的最大搜索二叉子树

分析可能性:1 最大搜索子树在左子树上
2 最大搜索子树在右子树上
3 最大搜索子树就是本身
对于情况3,需要满足左子树为搜索二叉树,右子树也为搜索二叉树,左子树的最大值小于根结点的值,右子树的最小值大于根结点的值
所以信息类

class Info {
public:
	int maxBSTSize;//最大二叉搜索子树中结点的个数
	int allSize;//树的总个数
	int max;//最大值
	int min;//最小值
};
#include<iostream>
#include<unordered_map>
using namespace std;
class Info {
public:
	int maxBSTSize;//最大二叉搜索子树中结点的个数
	int allSize;//树的总个数
	int max;//最大值
	int min;//最小值
	Info(int maxBSTSize, int allSize, int max, int min) :maxBSTSize(maxBSTSize), allSize(allSize), max(max), min(min) {

	}
};
class Node {
public:
	int val;
	Node* left;
	Node* right;
	Node(int val):val(val) {
		left = NULL;
		right = NULL;
	}
};
Info* process(Node* root) {
	if (root == NULL) {
		return NULL;
	}
	int max = root->val;
	int min = root->val;
	int maxBSTSize = 0;
	int allSize = 1;
	Info* leftInfo = process(root->left);
	Info* rightInfo = process(root->right);
	if (leftInfo) {
		max = leftInfo->max > max ? leftInfo->max : max;
		min= leftInfo->min < min ? leftInfo->min : min;
		allSize += leftInfo->allSize;
		
	}
	if (rightInfo) {
		max = rightInfo->max > max ? rightInfo->max : max;
		min = rightInfo->min < min ? rightInfo->min : min;
		allSize += rightInfo->allSize;
		
	}
	int p1 = -1;//情况1,最大搜索子树在左子树
	if (leftInfo != NULL) {
		p1 = leftInfo->maxBSTSize;
	}
	int p2 = -1;//情况2,最大搜索子树在右子树
	if (rightInfo != NULL) {
		p2 = rightInfo->maxBSTSize;
	}
	int p3 = -1;//情况3
	bool leftIsBST = leftInfo == NULL ? true : (leftInfo->allSize == leftInfo->maxBSTSize);//左子树是否为二叉搜索树
	bool rightIsBST = rightInfo == NULL ? true : (rightInfo->allSize == rightInfo->maxBSTSize);
	bool isBST = true;
	if (leftInfo) {
		if (leftInfo->max >= root->val) {
			isBST = false;
		}
		
	}
	if (rightInfo) {
		if (rightInfo->min <= root->val) {
			isBST = false;
		}
		
	}
	if (leftIsBST && rightIsBST && isBST) {//该树为二叉搜索树
		int leftSize = leftInfo == NULL ? 0 : leftInfo->allSize;
		int rightSize = rightInfo == NULL ? 0 : rightInfo->allSize;
		p3 = leftSize + rightSize + 1;
	}
	maxBSTSize = std::max(p1, std::max(p2, p3));
	return new Info(maxBSTSize, allSize, max, min);
}
int maxBstSize(Node* root) {
	if (root == NULL) {
		return 0;
	}
	return process(root)->maxBSTSize;
}
void print(Node* root) {
	if (root == NULL) {
		return;
	}
	print(root->left);
	cout << root->val << " ";
	print(root->right);
}
int main() {
	int n, root;
	unordered_map<int, Node*>nodes;
	cin >> n >> root;
	nodes.emplace(root, new Node(root));
	for (int i = 0; i < n; ++i) {
		int fa, lch, rch;
		cin >> fa >> lch >> rch;
		Node* head = nodes[fa];
		if (lch == 0) {
			head->left = NULL;
		}
		else {
			Node* leftNode = new Node(lch);
			nodes.emplace(lch, leftNode);
			head->left = leftNode;
		}
		if (rch == 0) {
			head->right = NULL;
		}
		else {
			Node* rightNode = new Node(rch);
			nodes.emplace(rch, rightNode);
			head->right = rightNode;
		}
	}
	Node* head = nodes[root];
	cout << maxBstSize(head);
	return 0;
}

判断是否为完全二叉树

以某个结点为根的树列可能性:
1 左子树为满二叉树,右子树为满二叉树,左右子树高度一样,则为完全二叉树
2 左子树为完全二叉树,右子树为满二叉树,左子树高度等于右子树高度+1
3 左子树为满二叉树,右子树为满二叉树,左子树高度等于右子树高度+1
4 左子树为满二叉树,右子树为完全二叉树,左子树高度等于右子树高度
以上4中情况满足一个即为完全二叉树。
要想判断该树是否为完全二叉树,需要知道子树是否为满二叉树,是否为完全二叉树,子树的高度
信息类:

class Info {
public:
	bool isFull;
	bool isCBT;
	int height;
	Info(bool isFull,bool isCBT,int height):isFull(isFull),isCBT(isCBT),height(height){}
};
class Info {
public:
	bool isFull;
	bool isCBT;
	int height;
	Info(bool isFull,bool isCBT,int height):isFull(isFull),isCBT(isCBT),height(height){}
};
class Node {
public:
	int val;
	Node* left;
	Node* right;
	Node(int val):val(val) {
		left = NULL;
		right = NULL;
	}
};
Info* process(Node* root) {
	if (root == NULL) {
		return new Info(true, true, 0);
	}
	Info* leftInfo = process(root->left);
	Info* rightInfo = process(root->right);
	bool isFull = leftInfo->isFull && rightInfo->isFull && leftInfo->height == rightInfo->height;
	int height = max(leftInfo->height, rightInfo->height) + 1;
	bool isCBT = false;
	if (leftInfo->isFull && rightInfo->isFull && leftInfo->height == rightInfo->height) {
		isCBT = true;
	}
	else if (leftInfo->isFull && rightInfo->isFull && leftInfo->height == rightInfo->height + 1) {
		isCBT = true;
	}
	else if (leftInfo->isCBT && rightInfo->isFull && leftInfo->height == rightInfo->height + 1) {
		isCBT = true;
	}
	else if (leftInfo->isFull && rightInfo->isCBT && leftInfo->height == rightInfo->height) {
		isCBT = true;
	}
	return new Info(isFull, isCBT, height);

}
bool isCBTree(Node* root) {
	return process(root)->isCBT;
}


给定一个头结点head,和另外两个结点a和b,返回a和b的最低公共祖先

思路:以X结点为根的树,返回a和b的最低公共祖先
1 X不是最低公共祖先
①左子树上有答案
②右子树上有答案
③X这棵树没有a或者没有b,即没有答案
2 X是最低公共最先
①左子树有a或者b,右子树有另外一个
②X就是a,左子树或右子树上有b
③X就是b,左子树或者右子树上有a

/**
 * 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:
    class Info {
        public:
            bool findA;
            bool findB;
            TreeNode* ans;
            Info(bool findA,bool findB,TreeNode* ans):findA(findA),findB(findB),ans(ans){
            }
        };
    Info* process(TreeNode* root, TreeNode* a, TreeNode* b) {
        if (root == NULL) {
            return new Info(false, false, NULL);
        }
        Info* leftInfo = process(root->left, a, b);
        Info* rightInfo = process(root->right, a, b);
        bool findA = (root == a) || leftInfo->findA || rightInfo->findA;
        bool findB = (root == b) || leftInfo->findB || rightInfo->findB;
        TreeNode* ans = NULL;
        if (leftInfo->ans != NULL) {
            ans = leftInfo->ans;
        }
        else if (rightInfo->ans != NULL) {
            ans = rightInfo->ans;
        }
        else {
            if (findA && findB) {
                ans = root;
            }
        }
        return new Info(findA, findB, ans);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        return process(root, p, q)->ans;
    }
};

派对的最大快乐值

题目描述:一个员工只有一个直接上级。也就是这个公司员工的层级结构就是一个多叉树。
现在公司邀请员工参加派对,要求不能同时邀请员工和员工的任一下级(即直接上下级不能同时邀请),如何邀请员工,才能使得参加派对的员工的快乐值是所有情况中最大的。最后返回最大的快乐值。
员工的定义如下:

class Employee {
public:
	int happy;
	vector<Employee*>nexts;
	Employee(int happy):happy(happy){}
};

思路:以x为根结点树,返回最大的快乐值
情况1 x来的话,返回最大值
最大值=x的快乐值+所有后代不来的最大值
情况2 x不来的话,返回最大值
最大值=所有后代来的最大值和不来的最大值最大的加起来

#include<iostream>
#include<vector>
using namespace std;

class Employee {
public:
	int happy;
	vector<Employee*>nexts;
	Employee(int happy):happy(happy){}
};
class Info {
public:
	int yes;
	int no;
	Info(int yes,int no):yes(yes),no(no){}
};
Info* process(Employee* root) {
	if (root == NULL) {
		return new Info(0, 0);
	}
	int yes = root->happy;
	int no = 0;
	for (Employee* e : root->nexts) {
		Info* next = process(e);
		yes += next->no;
		no += max(next->yes, next->no);
	}
	return new Info(yes, no);
}
int maxVal(Employee* root) {
	Info* allInfo = process(root);
	return max(allInfo->yes, allInfo->no);
}
int main() {
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值