代码随想录算法训练营第15天||● 层序遍历 10 ● 226.翻转二叉树 ● 101.对称二叉树 2

层序遍历:一共有十个题目

力扣题目链接:102.二叉树的层序遍历

层序遍历其实并不难。这个题目的难点在于题目要求返回的是一个二维数组。你需要将每层的元素放在一个数组中然后加入到二维数组中。

那就意味着,你不能直接一次性遍历下去,而是需要一个size来记录每一层节点的数量。

二叉树的层序遍历可以使用队列来实现。如果题目不要求输出二维数组的话,可以直接通过将根节点先加入队列,然后写一个while循环,先将队头元素出队,然后记录队头元素,然后将队头元素的左孩子和右孩子都加入队列中,直到队列中没有元素,停止循环。

这题需要记录每一层的孩子个数,所以我们不能一个while循环用到底,而是需要用一个整数size来记录每层节点的个数,然后再while循环中再写一个while循环,循环次数为该层节点的个数。

代码如下:

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        vector<vector<int>> result;
        if(root==NULL) return result;
        que.push(root);
        TreeNode*cur = root;
        while(!que.empty())
        {
            vector<int> vec;
            int size = que.size();
            while(size--)
            {
                cur = que.front();
                que.pop();
                vec.push_back(cur->val);
                if(cur->left)
                {
                    que.push(cur->left);
                }
                if(cur->right) que.push(cur->right);
            }
            result.push_back(vec);
        }
        return result;
    }
};

力扣题目链接:107.二叉树的层序遍历Ⅱ

这个题目看上去非常复杂,第一时间看到,可能会想半天该怎么把cur指针指向最后一层。

但是仔细看看题目,其实不难想到可以先用上一题的层序遍历求出结果,然后在返回结果的时候将结果数组反转就行了。

代码如下:

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> result;
        queue<TreeNode*> que;
        if(root==NULL) return result;
        que.push(root);
        TreeNode*cur = root;
        while(!que.empty())
        {
            vector<int> vec;
            int size = que.size();
            while(size--)
            {
                cur = que.front();
                que.pop();
                vec.push_back(cur->val);
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            result.push_back(vec);
        }
        reverse(result.begin(),result.end());
        return result;
    }
};

力扣题目链接:199.二叉树的右视图

这题也可以用层序遍历的方法。普通层序遍历是将每一层的所有元素都放入数组,这题可以只把每一层的最右边元素放入数组。还是用一个size记录每层的节点个数。但是只有在size==0的时候,才把节点的元素值加入数组。这样就做到了将节点的最后一个元素放入数组中。

代码如下:

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        vector<int> result;
        queue<TreeNode*>que;
        if(root==NULL)return result;
        que.push(root);
        TreeNode*cur = root;
        while(!que.empty())
        {
            int size = que.size();
            //for(int i =0;i<size;i++)
            while(size--)
            {
                cur = que.front();
                que.pop();
                if(size==0) result.push_back(cur->val);
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
        }
        return result;
    }
};

力扣题目链接:637.二叉树的层平均值

这题还是比较简单。还是用层序遍历,需要用一个size来记录每层节点个数。然后可以定义一个数,来记录每层节点元素值的和,然后除原先的size就能得到平均值。

代码如下:

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        vector<double> result;
        queue<TreeNode*>que;
        if(root==NULL) return result;
        TreeNode*cur = root;
        que.push(root);
        while(!que.empty())
        {
            int size = que.size();
            int size1 = size;
            double nums = 0;
            while(size--)
            {
                cur = que.front();
                que.pop();
                nums += cur->val; 
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            double ave = nums/size1;
            result.push_back(ave);
        }
        return result;
    }
};

力扣题目链接:429.N叉树的层序遍历

要做这个题,我们得先了解N叉树得定义。毕竟二叉树得节点中只有两个指针,而N叉树中是通过一个数组来存放孩子节点的。知道这个之后,其实进行层序遍历的做法就和二叉树差不多了,还是用size来记录每层节点的个数。

需要注意的是,要将N叉树的所有孩子遍历也需要用来一个循环,来从左到右遍历其孩子。

代码如下:

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> result;
        queue<Node*> que;
        if(root==NULL) return result;
        Node*cur = root;
        que.push(root);
        while(!que.empty())
        {
            vector<int> vec;
            int size = que.size();
            while(size--)
            {
                cur = que.front();
                que.pop();
                vec.push_back(cur->val);
                for(int i =0;i<cur->children.size();i++)
                {
                    if(cur->children[i]) que.push(cur->children[i]);
                }
            }
            result.push_back(vec);
        }
        return result;
    }
};

力扣题目链接:515.在每个数行中找最大值

这题还是很简单,还是层序遍历。我们可以定义一个数max,令他为最小值也就是max=INT32_MIN,用一个三目运算符max = max>cur->val?max:cur->val;来记录每层中的最大值。

代码如下:

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        vector<int> result;
        queue<TreeNode*>que;
        if(root==NULL) return result;
        TreeNode*cur = root;
        que.push(root);
        while(!que.empty())
        {
            int size = que.size();
            int max = INT32_MIN;
            while(size--)
            {
                cur = que.front();
                que.pop();
                max = max>cur->val?max:cur->val;
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            result.push_back(max);
        }
        return result;
    }
};

力扣题目链接:116.填充每个节点的下一个右侧节点指针

这题还是挺麻烦的。前面的题目内存循环我们用的几乎都是while循环,但是while循环很难找到第一个节点。而且前面的题目基本上只用了一个位置指针,这题我们需要两个位置指针。所以这题,我们内存循环使用for循环,先将每一层的第一个节点取出来。两个位置指针最开始都指向每层的第一个节点。然后其中位置指针cur1接收从队列中弹出来的节点,也就是除第一个节点外的后续节点。将第一个节点的位置指向,后续节点。然后在将第一个节点位置换到后续节点的位置。

也算是一种双指针法吧。

代码如下:

class Solution {
public:
    Node* connect(Node* root) {
        if(root==NULL) return root;
        queue<Node*>que;
        que.push(root);
        while(!que.empty())
        {
            Node*cur1;
            Node*cur2;
            int size = que.size();
            for(int i =0;i<size;i++)
            {
                if(i==0)
                {
                    cur1 = que.front();
                    que.pop();
                    cur2 = cur1;
                }
                else
                {
                    cur1 = que.front();
                    que.pop();
                    cur2 ->next = cur1;
                    cur2 = cur1;
                }
                if(cur1->left) que.push(cur1->left);
                if(cur1->right) que.push(cur1->right);
            }
        }
        return root;
    }
};

力扣题目链接:117.填充每个节点的下一个右侧节点指针Ⅱ

和上一题一模一样的思路和代码。

力扣题目链接:104.二叉树的最大深度

这题可以用层序遍历的方法,只需要在循环前定义一个深度deep,每遍历一层将deep+1.

代码如下:

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(root==NULL) return 0;
        queue<TreeNode*>que;
        que.push(root);
        TreeNode*cur = root;
        int deep = 0;
        while(!que.empty())
        {
            int size = que.size();
            while(size--)
            {
                cur = que.front();
                que.pop();
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
            deep = deep +=1;
        }
        return deep;
    }
};

力扣题目链接:111.二叉树的最小深度

这题其实也不难,还是用层序遍历的方法,加一个条件,就是位置指针指向的节点左右孩子都为空则是最小深度。

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(root==NULL ) return 0;
        queue<TreeNode*> que;
        que.push(root);
        TreeNode*cur = root;
        int deep = 0;
        while(!que.empty())
        {
            deep = deep+1;
            int size = que.size();
            while(size--)
            {
                cur = que.front();
                que.pop();
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
                if(!cur->left&&!cur->right) return deep;
            }
        }
        return deep;
    }
};

力扣题目链接:226.翻转二叉树

这题很简单,直接用递归,递归结束条件为根节点指向空。递归内容为建立一个临时节点,用来存放左孩子,然后将左孩子和右孩子交换。将左孩子和右孩子重新执行一遍代码。

代码如下:

class Solution {
public:
    void digui(TreeNode*root)
    {
        if(root==NULL) return;
        TreeNode*temp = root->left;
        root->left = root->right;
        root->right = temp;
        digui(root->left);
        digui(root->right);
    }
    TreeNode* invertTree(TreeNode* root) {
        digui(root);
        return root;
    }
};

力扣题目链接:101.对称二叉树

这个题,我第一时间的想法是,将左子树进行翻转,然后判断左右子树是否相等,如果相等则返回true,如果不相等则返回false。后来写了一下代码发现不行。

看了一下卡哥的讲解。总结了一下本题的解法:

可以使用递归的方式,比较左右子树的位置和值。使用后序遍历的方式,也就是从最后一层节点开始比较,然后慢慢往上比较。必须左右子树的位置为镜像并且值相等都满足才返回true。

具体讲解还是看代码随想录,我讲不太清楚。

代码如下:

class Solution {
public:
    bool digui(TreeNode*left,TreeNode*right)
        {
            if(left!=NULL&&right==NULL) return false;
            else if(left==NULL&&right!=NULL) return false;
            else if(left==NULL&&right==NULL) return true;
            else if(left->val!=right->val) return false;
            bool waice = digui(left->left,right->right);
            bool neice = digui(left->right,right->left);
            bool result = waice&&neice;
            return result; 
        }
    bool isSymmetric(TreeNode* root) {
        if(root==NULL) return true;
        return digui(root->left,root->right);
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值