我在代码随想录|写代码Day16之二叉树-二叉树的层序遍历, 二叉树的层次遍历 II, 二叉树的右视图,N叉树的层序遍历,在每个树行中找最大值,填充每个节点的下一个右侧节点指针,二叉树的最大/小深度

学习目标:

博主介绍: 27dCnc
专题 : 数据结构帮助小白快速入门
👍👍👍👍👍👍👍👍👍👍👍👍
☆*: .。. o(≧▽≦)o .。.:*☆

主题: 二叉树

今日份打卡
在这里插入图片描述

  • 代码随想录-二叉树


学习内容:

  1. 二叉树的层序遍历
  2. 二叉树的层次遍历 II
  3. 二叉树的右视图
  4. 二叉树的层平均值
  5. N叉树的层序遍历
  6. 在每个树行中找最大值
  7. 填充每个节点的下一个右侧节点指针
  8. 填充每个节点的下一个右侧节点指针II
  9. 二叉树的最大深度
  10. 二叉树的最小深度

内容讲解:

二叉树的层序遍历模版题

题目
二叉树的层序遍历
层序遍历
图解
二叉树层序遍历图解
思路解析:

俩个重要容器

  1. queue<TreeNode*>que; 队列
  2. `vector<vector> 二维数组

队列用于储存每一层的结点
二维数组用于储存每已成都结果

终止条件是队列为空,只要根结点不为空,就将根结点放入队列,进入循环后,队列的长度为每一层遍历的大小,然后将父节点的孩子结点放入队列,然后将父节点出队列,将父节点的值储存在新建立的vector<int>中然后不断循环每一层循环后将vwctor<int>放入vector<vector<int>>

层序遍历顺序

  1. 创建队列储存每一层结果
  2. 创建二维数组用于储存每一层的结果
  3. 进入循环去遍历每一层结果,终止条件是队列为空
  4. 用 size 储存二叉树中每一层的数组
  5. vector<int>储存每一层数组的值
  6. 将根结点的左右孩子放入队列中

代码

/**
 * 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:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        vector<vector<int>> ans;
        if(root != nullptr) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            vector<int>vec;
            for(int i = 0;i < size;i++) {
                TreeNode*node = que.front();
                que.pop();
                vec.push_back(node->val);
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            ans.push_back(vec);
        }
        return ans;
    }
};

二叉树的层序遍历 II

题目
二叉树的层序遍历 II
代码

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*> que;
        if(root != nullptr) que.push(root);
        vector<vector<int>> ans;
        while(!que.empty()){
            int size = que.size();
            vector<int> vec;
            for(int i=0;i<size;i++){
                TreeNode*node = que.front();
                que.pop();
                vec.push_back(node->val);
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            ans.push_back(vec);//记录每一层
        }
        reverse(ans.begin(),ans.end());
        return ans;
    }
};

reverse()用于反转层序遍历结果可以达到从下到上的遍历效果

199.二叉树的右视图

题目
二叉树的右视图
思路

可以层序遍历然后取层序遍历的最右边的数据,然后将数据存储到vector数组中返回
层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了,其中result数组即vector数组。

代码

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
         vector<int>ans;
         queue<TreeNode*>que;
         if(root != nullptr) que.push(root);
         while(!que.empty()) {
             int size = que.size();
             for(int i=0;i<size;i++){
                TreeNode*node = que.front();//取栈顶元素即上一层元素
                que.pop();//弹出元素准备放入该弹出元素的孩子结点
                if(i==size-1) ans.push_back(node->val);//没一层的最右的结点
                if(node->left) que.push(node->left);遍历树
                if(node->right) que.push(node->right);
             }
         }
         return ans;
    }
};

637. 二叉树的层平均值

题目
二叉树的层最大值

思路: 本题就是层序遍历的时候把一层求个总和在取一个均值。

代码

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        vector<double>ans;
        queue<TreeNode*>que;
        if(root != nullptr) que.push(root);
        while(!que.empty()) {
            long long sum = 0;
            int size = que.size();
            vector<int>vec;
            for(int i=0;i<size;i++) {
                TreeNode*node = que.front();
                que.pop();
                vec.push_back(node->val);
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            for(int i=0;i<size;i++) {
                sum+=vec[i];
            }
            ans.push_back(1.0*sum/size);
        }
        return ans;
    }
};

层序遍历模版 + 求数组平均值 + 将数组传入改为将平均值传入

429. N 叉树的层序遍历

题目

N 叉树的层序遍历

层序遍历进阶

N叉树与二叉树的不同

  • N叉树相较于二叉树孩子数量不同而且不国定
  • 结构并不平衡孩子结点的定义规则不同

N叉树定义

// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};

二叉树定义

   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) {}
 };

解决多孩子问题可以用遍历数组的方式

多孩子遍历

因为孩子是通过vector<Node*> children;储存的所以可以使用 node->children.size()统计数组长度,通过 if(node -> children[i]) que.push(node->children[i]);去遍历树的孩子。

层序遍历

代码

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

515.在每个树行中找最大值

题目

在每个树行中找最大值

思路 : 层序遍历,取每一层的最大值

代码

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        queue<TreeNode*> que;
        if(root != nullptr) que.push(root);
        vector<int> ans;
        while(!que.empty()){
            int size = que.size();
            vector<int> vec;
            for(int i=0;i<size;i++){
                TreeNode*node = que.front();
                que.pop();
                vec.push_back(node->val);
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            sort(vec.begin(),vec.end());
            ans.push_back(vec[size-1]);//记录每一层最大值
        }
        return ans;
    }
};

其他版本

Python

class Solution:
    def largestValues(self, root: TreeNode) -> List[int]:
        if not root:
            return []

        result = []
        queue = collections.deque([root])

        while queue:
            level_size = len(queue)
            max_val = float('-inf')

            for _ in range(level_size):
                node = queue.popleft()
                max_val = max(max_val, node.val)

                if node.left:
                    queue.append(node.left)

                if node.right:
                    queue.append(node.right)

            result.append(max_val)

        return result

Java

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        if(root == null){
            return Collections.emptyList();
        }
        List<Integer> result = new ArrayList();
        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            int max = Integer.MIN_VALUE;
            for(int i = queue.size(); i > 0; i--){
               TreeNode node = queue.poll();
               max = Math.max(max, node.val);
               if(node.left != null) queue.offer(node.left);
               if(node.right != null) queue.offer(node.right);
            }
            result.add(max);
        }
        return result;
    }
}

Go

/**
515. 在每个树行中找最大值
 */
func largestValues(root *TreeNode) []int {
    if root == nil {
        //防止为空
        return nil
    }
    queue := list.New()
    queue.PushBack(root)
    ans := make([]int, 0)
    temp := math.MinInt64
    // 层序遍历
    for queue.Len() > 0 {
        //保存当前层的长度,然后处理当前层(十分重要,防止添加下层元素影响判断层中元素的个数)
        length := queue.Len()
        for i := 0; i < length; i++ {
            node := queue.Remove(queue.Front()).(*TreeNode)//出队列
            // 比较当前层中的最大值和新遍历的元素大小,取两者中大值
            temp = max(temp, node.Val)
            if node.Left != nil {
                queue.PushBack(node.Left)
            }
            if node.Right != nil {
                queue.PushBack(node.Right)
            }
        }
        ans = append(ans, temp)
        temp = math.MinInt64
    }
    return ans
}

func max(x, y int) int {
    if x > y {
        return x
    }
    return y
}

116.填充每个节点的下一个右侧节点指针

题目

填充每个节点的下一个右侧节点指针
样例图解
1
思路
本题依然是层序遍历,只不过在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点就可以了

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> que;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            // vector<int> vec;
            Node* nodePre;
            Node* node;
            for (int i = 0; i < size; i++) {
                if (i == 0) {
                    nodePre = que.front(); // 取出一层的头结点
                    que.pop();
                    node = nodePre;
                } else {
                    node = que.front();
                    que.pop();
                    nodePre->next = node; // 本层前一个节点next指向本节点
                    nodePre = nodePre->next;
                }
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            nodePre->next = NULL; // 本层最后一个节点指向NULL
        }
        return root;

    }
};

117. 填充每个节点的下一个右侧节点指针 II

题目

填充每个节点的下一个右侧节点指针 II

思路
这道题目说是二叉树,但116题目说是完整二叉树,其实没有任何差别,一样的代码一样的逻辑一样的味道

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> que;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            Node* nodePre;
            Node* node;
            for (int i = 0; i < size; i++) {
                if (i == 0) {
                    nodePre = que.front(); // 取出一层的头结点
                    que.pop();
                    node = nodePre;
                } else {
                    node = que.front();
                    que.pop();
                    nodePre->next = node; // 本层前一个节点next指向本节点
                    nodePre = nodePre->next;
                }
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            nodePre->next = NULL; // 本层最后一个节点指向NULL
        }
        return root;
    }
};

104. 二叉树的最大深度

题目

二叉树的最大深度

思路
使用迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。
在二叉树中,一层一层的来遍历二叉树,记录一下遍历的层数就是二叉树的深度

深度与高度

递归法

class Solution {
public:
     int maxDepth(TreeNode* root) {
        if (root == nullptr) {
            return 0;
        }
        int depth_left = maxDepth(root->left);
        int depth_right = maxDepth(root->right);
        return 1 + max(depth_left, depth_right);
    }
};

迭代法

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (root == NULL) return 0;
        int depth = 0;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()) {
            int size = que.size();
            depth++; // 记录深度
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return depth;
    }
};

回溯法

class Solution {
public:
    int result;
    void getDepth(TreeNode* node,int depth) {
        result = depth > result ? depth : result;//中

        if (node->left == nullptr && node->right == nullptr) return ;

        if(node->left) { //左
            depth++;//深度+1
            getDepth(node->left,depth);
            depth--;//回溯深度-1 ,变向状态转换
        }
        if (node->right) {
            depth++;//深度+1
            getDepth(node->right,depth);
            depth--;//回溯深度-1 ,变向状态转换
        }
        return ;
    }
     int maxDepth(TreeNode* root) {
       result=0;
       if (root == nullptr) return result;
       getDepth(root,1);
       return result;
    }
};

111.二叉树的最小深度

题目

二叉树最小深度

思路

相对于 104.二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。

需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点

递归法

class Solution {
public:
    int minDepth(TreeNode* root) {
              if (root == nullptr) {
            return 0;
        }
        int depth_left = minDepth(root->left);
        int depth_right = minDepth(root->right);
        if(root->left == nullptr || root->right == nullptr){
            return 1 + max(depth_left, depth_right);
        }else{
            return 1 + min(depth_left, depth_right);
        }
    }
};

六花


学习时间:

  • 周一至周五晚上 7 点—晚上9点
  • 周六上午 9 点-上午 11 点
  • 周日下午 3 点-下午 6 点

学习产出:

  • 技术笔记 2 遍
  • CSDN 技术博客 3 篇
  • 习的 vlog 视频 1 个

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~

  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值