110.平衡二叉树
一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
要比较高度需要使用后序遍历。
递归三步曲分析:
1. 明确递归函数的参数和返回值:
参数:当前传入节点。 返回值:以当前传入节点为根节点的树的高度。
所以如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了。相当于剪枝
2. 明确终止条件
递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0
3. 单层递归的逻辑
分别求出其左右子树的高度,然后如果差值小于等于1,则返回当前二叉树的高度,否则返回-1,表示已经不是二叉平衡树了。
class Solution {
public:
int getheight(TreeNode* root){
if(root==NULL) return 0;
int leftheight = getheight(root->left);
if(leftheight==-1) return -1;
int rightheight = getheight(root->right);
if(rightheight==-1) return -1;//表示已经不是二叉平衡树了
int result;
if(abs(leftheight-rightheight)>1){
result = -1;
}else{
result =1+ max(leftheight, rightheight);
}
return result;
}
bool isBalanced(TreeNode* root) {
return getheight(root)==-1? false:true;
}
};
257. 二叉树的所有路径
给定一个二叉树,返回所有从根节点到叶子节点的路径。
根节点到叶子的路径,所以需要前序遍历,且涉及回溯算法,因为我们需要把路经记录下来。
递归三部曲:
1. 递归函数参数以及返回值
要传入根节点,记录每一条路径的path,和存放结果集的result,这里递归不需要返回值
void Tranverse(TreeNode* node, vector<int>& path, vector<string>& result)
2. 递归终止条件
本题要找到叶子节点,就开始结束的处理逻辑了(把路径放进result里)。
那么什么时候算是找到了叶子节点? 是当 cur不为空,其左右孩子都为空的时候,就找到叶子节点。
if(cur->left==NULL&&cur->right==NULL){}
使用vector 结构path来记录路径,所以要把vector 结构的path转为string格式,再把这个string 放进 result里。
if(node->left==NULL&&node->right==NULL){
string str;
for(int i=0; i<path.size()-1; i++){//将path里记录的路径转为string格式
str = str+to_string(path[i]);
str = str+"->";
}
str = str + to_string(path[path.size()-1]);
result.push_back(str);
return
}
3. 单层递归逻辑
因为是前序遍历,需要先处理中间节点,中间节点就是我们要记录路径上的节点,先放进path中。
path.push_back(cur->val);
然后是递归和回溯的过程,上面说过没有判断cur是否为空,那么在这里递归的时候,如果为空就不进行下一层递归了。回溯和递归是一一对应的,有一个递归,就要有一个回溯。
if (cur->left) {
traversal(cur->left, path, result);
path.pop_back(); // 回溯
}
if (cur->right) {
traversal(cur->right, path, result);
path.pop_back(); // 回溯
}
可以得到整体代码:
class Solution {
public:
void Tranverse(TreeNode* node, vector<int>& path, vector<string>& result){
path.push_back(node->val);
if(node->left==NULL&&node->right==NULL){
string str;
for(int i=0; i<path.size()-1; i++){//将path里记录的路径转为string格式
str = str+to_string(path[i]);
str = str+"->";
}
str = str + to_string(path[path.size()-1]);
result.push_back(str);
return;
}
if(node->left){
Tranverse(node->left, path, result);
path.pop_back();
}
if(node->right){
Tranverse(node->right, path, result);
path.pop_back();
}
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<int> path;
vector<string> result;
if (root == NULL) return result;
Tranverse(root, path, result);
return result;
}
};
最主要的是确定终止条件的那一步。
404.左叶子之和
计算给定二叉树的所有左叶子之和。
首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。
递归三部曲:
1. 递归函数的参数和返回值
判断一个树的左叶子节点之和,传入树的根节点,递归函数的返回值为数值之和,所以为int
使用题目中给出的函数就可以了。
2. 终止条件
if (root == NULL) return 0;
if (root->left == NULL && root->right== NULL) return 0;
3. 单层递归的逻辑
当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if(root==NULL) return 0;
if(root->left==NULL && root->right==NULL) return 0;
int leftsum = sumOfLeftLeaves(root->left);
if(root->left && root->left->left==NULL && root->left->right==NULL){
leftsum =root->left->val; //不用累加,因为每个结点的左叶子结点只有一个
}
int rightsum = sumOfLeftLeaves(root->right);
return leftsum+rightsum;
}
};
513.找树左下角的值
给定一个二叉树,在树的最后一行找到最左边的值。
先考虑层序遍历。
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
if(root==NULL) return 0;
que.push(root);
int result = 0;
while(!que.empty()){
int size = que.size();
for(int i=0; i<size; i++){
TreeNode* tmp = que.front();
que.pop();
if (i == 0) result = tmp->val;
if(tmp->left) que.push(tmp->left);
if(tmp->right) que.push(tmp->right);
}
}
return result;
}
};
考虑递归:
那么如何找最左边的呢?可以使用前序遍历(当然中序,后序都可以,因为本题没有 中间节点的处理逻辑,只要左优先就行),保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。
递归三部曲:
1. 递归函数的参数和返回值
参数必须有要遍历的树的根节点,还有就是一个int型的变量用来记录最长深度。这里就不需要返回值了,所以递归函数的返回类型为void。
类里的两个全局变量,maxLen用来记录最大深度,result记录最大深度最左节点的数值。
int maxDepth = INT_MIN; // 全局变量 记录最大深度
int result; // 全局变量 最大深度最左节点的数值
void traversal(TreeNode* root, int depth)
2. 终止条件
叶子节点的时候,需要统计一下最大的深度,所以需要遇到叶子节点来更新最大深度。
3. 单层递归的逻辑
// 中
if (root->left) { // 左
depth++; // 深度加一
traversal(root->left, depth);
depth--; // 回溯,深度减一
}
if (root->right) { // 右
depth++; // 深度加一
traversal(root->right, depth);
depth--; // 回溯,深度减一
}
return;
class Solution {
public:
int maxDepth = INT_MIN;
int result;
void tranverse(TreeNode* root, int depth){
if(root->left == NULL && root->right == NULL){
if(depth>maxDepth){
maxDepth = depth;
result = root->val;
}
return;
}
if(root->left){
depth++;//往下探索,深度加一
tranverse(root->left,depth);
depth--;//因为往回倒了,所以depth减一
}
if(root->right){
depth++;
tranverse(root->right,depth);
depth--;
}
return;
}
int findBottomLeftValue(TreeNode* root) {
tranverse(root, 0);
return result;
}
};