LeetCode二叉树经典题目(六):结构&回溯

目录

17. LeetCode101. 对称二叉树

18. LeetCode222. 完全二叉树的节点个数

19. LeetCode110. 平衡二叉树

20. LeetCode257. 二叉树的所有路径


17. LeetCode101. 对称二叉树

思路:
1.本质上就是在判断每个节点的左右子树翻转后是否和原先一样
2.以对称轴为中心轴,内侧和内侧的比较、外侧和外侧的比较
3.确定遍历顺序:only后序(左右中),因为我们需要左右子树的信息,才能判断是否能够翻转

递归:并非传统的向左右子节点要信息,而是向两个应当匹配的节点索要信息
class Solution {
public:
    bool compare(TreeNode*compareLeft,TreeNode*compareRight){
        //base case(确保非空后才可判断值)
        //前三种情况是判断结构,最后一种情况是判断值
        if(compareLeft!=NULL&&compareRight==NULL)return false;
        else if(compareLeft==NULL&&compareRight!=NULL)return false;
        else if(compareLeft==NULL&&compareRight==NULL)return true;
        else if(compareLeft->val!=compareRight->val)return false;

        //索要内侧和外侧的信息
        bool inside=compare(compareLeft->right,compareRight->left);
        bool outside=compare(compareLeft->left,compareRight->right);

        //只有当内侧和外侧的节点都符合要求时,整体才对称
        return inside&&outside;
    }

    bool isSymmetric(TreeNode* root) {
        return compare(root->left,root->right);
    }
};

迭代:
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        queue<TreeNode*>que;
        que.push(root->left);
        que.push(root->right);
        while(!que.empty()){
            //取出的两个节点是将要匹配的
            TreeNode*compareLeft=que.front();que.pop();
            TreeNode*compareRight=que.front();que.pop();
            if(!compareLeft&&!compareRight)continue;
            else if(!compareLeft||!compareRight||compareLeft->val!=compareRight->val)return false;
            //由于是按序取,所以也要按序存
            que.push(compareLeft->right);
            que.push(compareRight->left);
            que.push(compareLeft->left);
            que.push(compareRight->right);
        }
        return true;
    }
};

18. LeetCode222. 完全二叉树的节点个数

1.当作普通二叉树:
class Solution {
public:
    int countNodes(TreeNode* root) {
        if(root==NULL)return 0;
        int leftNodes=countNodes(root->left);
        int rightNodes=countNodes(root->right);
        return leftNodes+rightNodes+1;
    }
};

2.利用完全二叉树的特性:
2.1如果子树是完全满二叉树,利用公式(2^h-1)直接得出节点个数
2.2判断完全满二叉树:在完全二叉树的基础上,一直向左遍历的深度等于一直向右遍历的深度,就说明是完全满二叉树
class Solution {
public:
    int countNodes(TreeNode* root) {
        //base case
        if(root==NULL)return 0;
        
        //和普通二叉树唯一的区别:多了一步判断完全满二叉树,可以少遍历中间节点
        TreeNode*left=root->left;
        TreeNode*right=root->right;
        int leftDepth=0;
        int rightDepth=0;
        while(left){
            left=left->left;
            leftDepth++;
        }
        while(right){
            right=right->right;
            rightDepth++;
        }
        if(leftDepth==rightDepth){
            return (2<<leftDepth)-1;
        }

        //当前节点逻辑
        int leftNodes=countNodes(root->left);
        int rightNodes=countNodes(root->right);
        return leftNodes+rightNodes+1;
    }
};

19. LeetCode110. 平衡二叉树

class Solution {
public:
    class Info{
    public:
        bool isBalanced;
        int height;
        
        Info(bool isBalanced,int height){
            this->isBalanced=isBalanced;
            this->height=height;
        }
    };

    Info process(TreeNode*node){
        if(node==NULL)return Info(true,0);

        //向左右子树索要信息
        Info leftData=process(node->left);
        Info rightData=process(node->right);

        //处理当前节点信息
        bool isBalanced=(abs(leftData.height-rightData.height)<=1
        &&leftData.isBalanced
        &&rightData.isBalanced);

        int height=max(leftData.height,rightData.height)+1;

        return Info(isBalanced,height);
    }

    bool isBalanced(TreeNode* root) {
        Info data=process(root);
        return data.isBalanced;
    }
};

20. LeetCode257. 二叉树的所有路径

递归:
class Solution {
public:
    vector<string>res;

    void process(TreeNode*node,string path){
        if(node==NULL){
            return;
        }
        if(node->left==NULL&&node->right==NULL){//遍历到叶子节点才停止
            res.push_back(path+to_string(node->val));
            return;
        }
        process(node->left,path+to_string(node->val)+"->");
        process(node->right,path+to_string(node->val)+"->");
    }

    vector<string> binaryTreePaths(TreeNode* root) {
        process(root,"");
        return res;
    }
};

迭代:
class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        stack<TreeNode*>treeStk;//保存树的节点
        stack<string>pathStk;//保留路径
        vector<string>res;//最终路径集合
        treeStk.push(root);
        pathStk.push(to_string(root->val));
        while(!treeStk.empty()){
            TreeNode*node=treeStk.top();treeStk.pop();//取出该节点
            string path=pathStk.top();pathStk.pop();//取出该节点对应路径
            if(node->left==NULL&&node->right==NULL){//叶子节点
                res.push_back(path);
            }
            if(node->right){//栈:右先
                treeStk.push(node->right);
                pathStk.push(path+"->"+to_string(node->right->val));
            }
            if(node->left){
                treeStk.push(node->left);
                pathStk.push(path+"->"+to_string(node->left->val));
            }
        }
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jomo.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值