110.平衡二叉树
思路
1. 自顶向下递归
- 对于当前遍历到的节点,首先计算左右子树的高度
- 如果左右子树的高度差是否不超过1,再分别递归地遍历左右子节点
- 并判断左子树和右子树是否平衡。
2. 自底向上递归
- 对于当前遍历到的节点,先递归地判断其左右子树是否平衡,再判断以当前节点为根的子树是否平衡
- 如果一棵子树是平衡的,则返回其高度(高度一定是非负整数),否则返回−1
- 如果存在一棵子树不平衡,则整个二叉树一定不平衡。
代码
1. 自顶向下递归
class Solution {
public:
int getdepth(TreeNode* node){
if(node==NULL) return 0;
int left=getdepth(node->left);
int right=getdepth(node->right);
return max(left,right)+1;
}
bool isBalanced(TreeNode* root) {
if(root==NULL) return true;
if(abs(getdepth(root->left)-getdepth(root->right))>1) return false;
bool left=isBalanced(root->left);
bool right=isBalanced(root->right);
return left&&right;
}
};
- 时间复杂度
O(n^2)
- 空间复杂度
O(n)
2. 自底向上递归
class Solution {
public:
int getHeight(TreeNode* node){
if(node==NULL) return 0;
int leftHeight=getHeight(node->left);
if(leftHeight==-1) return -1;
int rightHeight=getHeight(node->right);
if(rightHeight==-1) return -1;
if(abs(leftHeight-rightHeight)>1) return -1;
return max(leftHeight,rightHeight)+1;
}
bool isBalanced(TreeNode* root) {
if(getHeight(root)==-1) return false;
else return true;
}
};
- 时间复杂度
O(n)
- 空间复杂度
O(n)
257. 二叉树的所有路径
思路
1. 递归(深搜)
- 递归参数和返回值:根节点、每一条路径path、结果集result,无返回值
- 终止条件:遇到叶子结点终止
- 单层递归逻辑:需要回溯
2. 迭代(深搜)
- 前序非递归
代码
1. 递归(深搜)
class Solution {
public:
void traversal(TreeNode* cur,vector<int> &path,vector<string> &result){
path.push_back(cur->val);
if(cur->left==NULL&&cur->right==NULL){
string str;
for(int i=0;i<path.size()-1;i++){
str+=to_string(path[i]);
str+="->";
}
str+=to_string(path[path.size()-1]);
result.push_back(str);
return ;
}
if(cur->left){
traversal(cur->left,path,result);
path.pop_back();
}
if(cur->right){
traversal(cur->right,path,result);
path.pop_back();
}
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
vector<int> path;
traversal(root,path,result);
return result;
}
};
隐藏回溯:
class Solution {
public:
void traversal(TreeNode* cur,string path,vector<string> &result){
path+=to_string(cur->val);
if(cur->left==NULL&&cur->right==NULL){
result.push_back(path);
return ;
}
if(cur->left) traversal(cur->left,path+"->",result);
if(cur->right) traversal(cur->right,path+"->",result);
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
string path;
traversal(root,path,result);
return result;
}
};
2. 迭代
class Solution {
public:
vector<string> binaryTreePaths(TreeNode* root) {
stack<TreeNode*> treeSt;// 保存树的遍历节点
stack<string> pathSt; // 保存遍历路径的节点
vector<string> result; // 保存最终路径集合
treeSt.push(root);
pathSt.push(to_string(root->val));
while(!treeSt.empty()){
TreeNode* node=treeSt.top();treeSt.pop();
string path=pathSt.top();pathSt.pop();
if(node->left==NULL&&node->right==NULL){
result.push_back(path);
}
if(node->right){
treeSt.push(node->right);
pathSt.push(path+"->"+to_string(node->right->val));
}
if(node->left){
treeSt.push(node->left);
pathSt.push(path+"->"+to_string(node->left->val));
}
}
return result;
}
};
404.左叶子之和
思路
1. 递归法
方法一:
- 使用一个指针指向当前遍历到的结点的父节点,从而保证能够记录左叶子的数
方法二:
- 后序遍历,求出分别求出左右孩子的父节点,返回给上一层
方法三:
- 函数参数传入sum的引用,当当前指针指向的左孩子为叶子时,记录
2. 迭代法
方法一:
- 前序遍历+pre指针
方法二:
- 前序遍历+直接判断左叶子
代码
1. 递归法
方法一:
class Solution {
public:
void preorder(TreeNode* root,TreeNode* pre,int &sum){
if(root==nullptr) return;
if(root->left==NULL&&root->right==NULL){
if(pre->left==root) sum+=root->val;
}
pre=root;
preorder(root->left,pre,sum);
preorder(root->right,pre,sum);
}
int sumOfLeftLeaves(TreeNode* root) {
int sum=0;
preorder(root,root,sum);
return sum;
}
};
方法二:
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if(root==NULL) return 0;
if(!root->left&&!root->right) return 0;
int leftsum=sumOfLeftLeaves(root->left);
if(root->left&&!root->left->left&&!root->left->right){
leftsum+=root->left->val;
}
int rightsum=sumOfLeftLeaves(root->right);
return leftsum+rightsum;
}
};
方法三:
class Solution {
public:
void preorder(TreeNode* root,int &sum){
if(root==nullptr) return;
if(root->left&&root->left->left==NULL&&root->left->right==NULL){
sum+=root->left->val;
}
preorder(root->left,sum);
preorder(root->right,sum);
}
int sumOfLeftLeaves(TreeNode* root) {
int sum=0;
preorder(root,sum);
return sum;
}
};
- 时间复杂度
O(n)
- 空间复杂度
O(n)
2. 迭代法
方法一:
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
stack<TreeNode*> st;
int sum=0;
TreeNode* p=root;
TreeNode* pre=new TreeNode();
while(p||!st.empty()){
if(p){
if(p->left==NULL&&p->right==NULL){
if(pre->left==p) sum+=p->val;
}
st.push(p);
pre=p;
p=p->left;
}
else{
p=st.top();st.pop();
pre=p;
p=p->right;
}
}
return sum;
}
};
方法二:
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
stack<TreeNode*> st;
int sum=0;
TreeNode* p=root;
while(p||!st.empty()){
if(p){
if(p->left&&!p->left->left&&!p->left->right){
sum+=p->left->val;
}
st.push(p);
p=p->left;
}
else{
p=st.top();st.pop();
p=p->right;
}
}
return sum;
}
};
- 时间复杂度
O(n)
- 空间复杂度
O(n)