代码随想录第几天来着?忘记啦

38、对称二叉树

力扣原题

题目简介:

给你一个二叉树的根节点 root , 检查它是否轴对称。

初见思路:

​ 感觉没什么思路,是不是得用特定的遍历顺序呢?前、中、后序的特性,我的第一反应应该是。

算法思路:

​ 太妙了,实在是太妙了,后序遍历的魅力

​ 所谓后续遍历,就是要收集下方所有子树的信息之后,再进行处理根节点,只要符合这个思路的问题,应该都要这样做。

​ 还是三部曲:

​ 1、先确定返回值与形参:

​ 这里我就没想到了,我还想着的是一个节点一个节点处理,然后写的时候就发现根本不知道另一半子树的任何信息,所以失败了。应该将根节点的左、右子树都拿过来,然后再进行比较。

​ 2、确定终止条件:

​ 这里又没想到了,主要就是我把所有的情况都写出来了,左右都为空、左右一个不为空、左右都不为空然后判断是否值相等,值不等肯定就不能反转了,但是主要的,我以为值相等就会return true;了,然后我就发现不对了,左右相等就return吗?那不是完全不知道下面的树的情况了?

​ 所以,这里也是精髓,原来,如果左右值相等我们才进入下面的判断,也就是所谓的外侧与内侧判断。

​ 3、单层处理逻辑:

​ 这里就更是妙中之妙,玄之又玄!

​ 外侧结果,就是传入左子树的左边和右子树的右边!

​ 内侧结果,就是传入左子树的右边和右子树的左边!

​ 太妙了实在是,我一开始还完全不理解,我不是一直在半边进行判断吗?怎么知道另外半边的情况,这里由步骤2给出了解答。我还不知道怎么处理外侧和内侧,这里3给出了解答,我只能说卡哥牛逼!

/**
 * 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:

    bool traversal(TreeNode* left,TreeNode* right){
        if(left == nullptr && right == nullptr) return true;
        else if(left != nullptr&& right == nullptr) return false;
        else if(left == nullptr && right != nullptr) return false;
        else if(left != nullptr && right != nullptr){
            if(left->val != right->val) return false;
        }

        auto outresult = traversal(left->left,right->right);
        auto insresult = traversal(left->right,right->left);

        return outresult && insresult;
    }

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

39、二叉树最大深度

力扣原题

题目简介:

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

初见思路:

well,这道题就是层序遍历的经典题了,一层层的往下走,然后到了新的一层就可维护一个层高,然后层序遍历完之后就能找到depth了。

​ 经典的框架,这是第十一边写了。

/**
 * 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 maxDepth(TreeNode* root) {
        
        queue<TreeNode*> que;

        if(root != nullptr) que.push(root);
        int depth =0;
        while(!que.empty()){

            size_t size = que.size();
            depth++;
            while(size--){

                auto cur = que.front();
                que.pop();
                if(cur != nullptr){
                    
                    if(cur->left) que.push(cur->left);
                    if(cur->right) que.push(cur->right);
                }
            }
        }

        return depth;
        
    }
};

40、二叉树最小深度

力扣原题

题目简介:

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

**说明:**叶子节点是指没有子节点的节点。

初见思路:

​ 因为层序是从上往下走的,所以只要触发了停止条件就能保证,当前是最小的深度,而且每一层的元素是遍历的,所以不会有错漏的地方。

​ 现在再来谈一谈停止的条件,什么时候我们会说不会有下一层了,那就是一个节点的左、右子树都是nullptr的时候,那么就不会有下一层,他就是一个叶节点了。

​ 那么现在我们只要判断,哪一层的哪一个节点只要是叶节点了,那么这就是最小深度了。

/**
 * 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 minDepth(TreeNode* root) {

        queue<TreeNode*> que;
        if(root != nullptr) que.push(root);

        int depth = 0;
        while(!que.empty()){

            size_t size = que.size();
            depth++;
            
            while(size--){
                
                auto cur = que.front();
                que.pop();
                if(cur != nullptr){
                    if(cur->left) que.push(cur->left);
                    if(cur->right) que.push(cur->right);
                    if( cur->left == nullptr && cur->right == nullptr )
                        return depth;

                }
                
            }

        }

        return depth;

    }
};

二叉树的种类

1、满二叉树

​ 他的节点数量等于2^k-1,其中k是深度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2、完全二叉树

​ 除了底层,其他的节点都是满的,且底层从左到右都是连续的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3、二叉搜索树

​ 左子树都小于根节点,右子树都大于根节点。对于节点的结构没有太大的约束。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4、平衡二叉搜索树

​ 左子树和右子树的高度不能超过1;

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

​ 可以看见,左子树是一个平衡二叉搜索树,左右子树之间也只相差1的高度,所以这是一个平衡二叉搜索树。

41、完全二叉树的节点数量

力扣原题

题目简介:

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(从第 0 层开始),则该层包含 1~ 2h 个节点

初见思路:

​ 虽然我很想直接就层序遍历秒掉它,但是我觉得还是得听一听思路,因为这题明确了是一个完全二叉树,那一定就要用到完全二叉树的特点才行。

​ 那完全二叉树的特点有哪些呢?

​ 第一,除了底部可能是不满的,其他的节点都是满的。

​ 第二,底部从左到右是连续的。

​ 那么,我是不是只要知道底部的深度,然后知道底部从左到右有几个节点就ok了?那感觉还不如直接数就好了?

/**
 * 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 traversal(TreeNode* cur){
        if(cur == nullptr) return 0;

        int left = traversal(cur->left);
        int right = traversal(cur->right);

        return left+right +1;
    }

    int countNodes(TreeNode* root) {
        return traversal(root);
    }
};

​ 这就是遍历了所有的节点才行的方法。

算法思路:

​ 我的感觉就是算法思路就是做了一个剪枝,都新增了一个终止条件,也就是如果是满二叉树就直接返回一个2 * k - 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 traversal(TreeNode* cur){
        if(cur == nullptr) return 0;
        else{
            TreeNode* leftnode = cur->left;
            TreeNode* rightnode = cur->right;

            int leftdepth =0;
            int rightdepth = 0;
            while(leftnode){
                leftnode = leftnode->left;
                leftdepth++;
            }
            while(rightnode){
                rightnode = rightnode->right;
                rightdepth++;
            }
            if(leftdepth == rightdepth) return  (2 << leftdepth )-1;

            }

        
        int left = traversal(cur->left);
        int right = traversal(cur->right);

        return left+right +1;
    }

    int countNodes(TreeNode* root) {
        return traversal(root);
    }
};

​ 利用了完全二叉树的特点,对于一个完全二叉树,你大概率能找到一个满二叉树。然后直接剪枝计算不用递归了。

42、平衡二叉树

力扣原题

题目简介:

​ 给定一个二叉树,判断它是否是 平衡二叉树

初见思路:

​ 遍历左右的子树的高度,然后看看是不是每一个子树的左右子树高度差为1吗?

​ 注意,这里用的是高度,也就是而不是深度,所以,一个树的高度,等于他的最大深度。

​ 哎呀我咋写不出来呀,我能算出每个子树的高度,这没错,但是判断他是不是平衡二叉树的地方应该在什么地方呢?

算法思路:

​ 我无语了,算法思路中,直接用-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 traversal(TreeNode* cur) {

        if (cur == nullptr)
            return 0;


        int left = traversal(cur->left);
        int right = traversal(cur->right);
        if(left == -1 || right == -1) return -1;
        if((left-right) *(left-right) >1) return -1;
        else return max(left, right) + 1;
    }

    bool isBalanced(TreeNode* root) {
        int result = traversal(root);
        if(result != -1) return true;
        else return false;
    }
};

​ 这道题我觉得很好的锻炼了我的递归思维,我发现了在递归时信息传递的困难和什么时候应该传递信息,我觉得还是不错的。

43、二叉树的所有路径

力扣原题

题目简介:

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

初见思路:

​ 我能想到的就是定义一个二维数组,然后循环的时候每个节点再创建一个一维数组来保存节点,然后进入递归,最后把路径也存在二维数组里,然后一直把二维数组也作为形参传入递归中。

    void treversal(TreeNode* cur,vector<vector<TreeNode*>> & path){

        if(cur == nullptr) return;
        
        vector<TreeNode*> sonpah;
        sonpah.push_back(cur);
        treversal(cur->left,sonpah);
        treversal(cur->right,sonpah);
        path.push_back(sonpah);
    }

​ 大概是这种思路,但是我不敢保证这个路径的正确性,我的脑子不够了。而且我还不知道怎么输出一个vector<string>,尊武与。

/**
 * 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 treversal(TreeNode* cur,vector<int>&path,vector<string>&result){

        path.push_back(cur->val);
        if(cur->left == nullptr && cur->right == nullptr){
            string tem_path;
            for(int i=0;i<path.size()-1;i++){
                tem_path += to_string(path[i]);
                tem_path += "->";
            }
            tem_path +=to_string(path[path.size()-1]);
            result.push_back(tem_path);
            return ;
        }
        
        if(cur->left){
            treversal(cur->left,path,result);
            path.pop_back();
        }
        if(cur->right){
            treversal(cur->right,path,result);
            path.pop_back();
        }

    }


    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> result;
        vector<int> path;
        if(root==nullptr) return result;  
        treversal(root,path,result);
        return result;
    }
};

​ 救命,感觉回溯的感觉还是有点不理解,感觉和递归好像,但有完全是两个步骤,回溯更加是对于path来讲的,但是递归是对程序说的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值