(17/60)平衡二叉树、二叉树的所有路径、左叶子之和
年假后的第一天,感觉一切回到解放前T T
*衡二叉树
leetcode:110. *衡二叉树
后序递归求高度差法
思路
类似104. 二叉树的最大深度,求左右子树的最大深度(后序遍历求该点的最大高度,其实就等于该子树的最大深度)
复杂度分析
时间复杂度:O(N)。
空间复杂度:**衡时树为O(logN),极倾斜时为O(N)。
注意点
- 返回值是
1 + max(LHD,RHD)。(向上返回高度,从1开始)
代码实现
/**
* 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:
// 后序递归遍历
// 求左右节点高度差
int getHeightDiff(TreeNode* node){
if(node == NULL) return 0;
// 结果如果为-1则表示>1 继续向上返回-1
int LHD = getHeightDiff(node->left);
if(LHD == -1) return -1;
int RHD = getHeightDiff(node->right);
if(RHD == -1) return -1;
int result = 0;
if(abs(LHD - RHD) > 1) result = -1;
else result = 1 + max(LHD,RHD);
return result;
}
bool isBalanced(TreeNode* root) {
return getHeightDiff(root) != -1 ? true : false;
}
};
二叉树的所有路径
leetcode:257. 二叉树的所有路径
前序递归遍历
思路
首先要使用前序遍历,以利用递归调用(调用自身)的过程实现根->叶的指向。
个人理解:递归算法每层递归都包含递归调用(调用自身进入下一层递归)、递归回溯(触发返回条件,返回上层递归)两个部分,前序遍历在递归调用过程中进行处理(例如此题,自上而下遍历、层层深入时处理路径),后序遍历在递归回溯过程中进行处理(例如求最大深度,自底向上返回节点高度)。
- 先将当前节点放入path;
- 如果为叶节点,则将当前path加入结果数组中;
- 对左、右节点进行处理和path的回溯。(
path.pop_back())
复杂度分析
时间复杂度:O(N)。
空间复杂度:二叉树递归遍历,**衡时O(logN),极倾斜时O(N)。
注意点
- to_string()函数
代码实现
回溯逻辑版:(对path的结果都被保存下来,回溯时应该回到原来状态,所以要补一句path.pop_back())
/**
* 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:
// 递归回溯 前序遍历
void findPath(TreeNode* node,vector<int>& path,vector<string>& result){
path.push_back(node->val); // 中
// 左右都为空,为叶子节点
if(node->left == NULL && node->right == NULL){
string spath;
for(int i = 0;i < path.size() - 1; i++){
spath += to_string(path[i]);
spath += "->";
}
spath += to_string(path[path.size() - 1]);
result.push_back(spath);
return;
}
if(node->left){
findPath(node->left,path,result);
path.pop_back(); // 回溯
}
if(node->right){
findPath(node->right,path,result);
path.pop_back(); // 回溯
}
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<int> path;
vector<string> result;
if(root == NULL) return result;
else findPath(root,path,result);
return result;
}
};
精简版:(因为传入参数时没有对变量path进行修改,而是直接传入修改后的值,内层path加的"->"不会被保存下来;另外,由于没有用&引用,开头的+= to_string(node->val)也没有被保存,天然“回溯”)
/**
* 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:
// 精简版
void traversal(TreeNode* node,string path,vector<string>& result){
path += to_string(node->val);
if(node->left == NULL && node->right == NULL){
result.push_back(path);
return;
}
if(node->left) traversal(node->left,path + "->",result);
if(node->right) traversal(node->right,path + "->",result);
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
if(root == NULL) return result;
else traversal(root,"",result);
return result;
}
};
返回左叶子之和
leetcode:404. 左叶子之和
递归遍历法
思路
遍历节点,如果节点满足1. 是叶节点;2. 是左节点,则sum+=node->val。
本来打算说写后序自下而上返回sum,结果写成了前中后序都可以的。
复杂度分析
时间复杂度:O(N)。
空间复杂度:递归遍历二叉树,**衡时O(logN),极倾斜时O(N)。
注意点
略
代码实现
通用递归版:
/**
* 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:
// 遍历节点,如果节点是叶,且是左节点则加入sum,选择后序遍历。
void traverseLeftSum(TreeNode* node,int index,int& sum){
// index是左右子树标记,左子树为1,右子树为2,根为0
if(node == NULL) return;
if(node->left) traverseLeftSum(node->left,1,sum);
if(node->right) traverseLeftSum(node->right,2,sum);
if(node->left == NULL && node->right == NULL && index == 1){
sum += node->val;
}
}
int sumOfLeftLeaves(TreeNode* root) {
int sum = 0;
if(root->left == NULL && root->right == NULL)
return 0;
else traverseLeftSum(root,0,sum);
return sum;
}
};
后序遍历版通用版二:(想写后序遍历结果又是通用版)
/**
* 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:
// 遍历节点,如果节点是叶,且是左节点则加入sum,选择后序遍历。
int traverseLeftSum(TreeNode* node,int index){
// index是左右子树标记,左子树为1,右子树为2,根为0
int sum = 0; // 每一层的sum
if(node == NULL) return 0; // 结束条件
if(node->left) sum += traverseLeftSum(node->left,1);
if(node->right) sum += traverseLeftSum(node->right,2);
if(node->left == NULL && node->right == NULL && index == 1){
sum += node->val;
}
return sum;
}
int sumOfLeftLeaves(TreeNode* root) {
if(root->left == NULL && root->right == NULL)
return 0;
else return traverseLeftSum(root,0);
}
};
后序遍历法:
/**
* 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:
int sumOfLeftLeaves(TreeNode* root) {
if(root == NULL) return 0;
// 左子树是叶子情况的处理
int leftVal = 0;
if(root->left && !root->left->left && !root->left->right)
leftVal = root->left->val;
return leftVal + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
}
};

浙公网安备 33010602011771号