Leetcode每日一题5.29:二叉树的递归遍历和层序遍历

二叉树刷了十几道题才想起来记录,由于数据结构忘了好多,树的部分容易养成代码框架化思维,所以从二叉树开始刷起。

二叉树

二叉树有两种遍历方式:

  1. 深度优先遍历:从根节点往深走,遇到叶子节点再往回走。
    (1)前序遍历(根左右)
    (2)中序遍历(左根右)
    (3)后序遍历(左右根)

  2. 广度优先遍历:一层一层进行遍历。

一、递归遍历

先写一个最简单的前序遍历

144. 二叉树的中序遍历

题目描述:
给定一个二叉树的根节点 root ,返回它的中序遍历。

示例:
在这里插入图片描述
代码题解:

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        inorder(root, res);
        return res;
    }

    // 递归函数
    void inorder(TreeNode* root, vector<int>& res) {   // 确定 参数 和 返回类型(利用res数组来存放节点的数值,所以不需要有返回值)
        if (root == nullptr) return;  // 终止条件

        // 单层递归逻辑
        inorder(root -> left, res);  // 左
        res.push_back(root -> val);  // 根
        inorder(root -> right, res); // 右
    }
};

671. 二叉树中第二小的节点

题目描述:

  • 给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话,那么该节点的值等于两个子节点中较小的一个。 更正式地说,即 root.val = min(root.left.val, root.right.val) 总成立。
  • 要求:给出这样的一个二叉树,你需要输出所有节点中的 第二小的值 。如果第二小的值不存在的话,输出 -1 。

示例:
在这里插入图片描述
思路: 每个节点的子节点树不是2就是0,那么如果有子节点,根节点就是值最小的节点。

代码题解:

public:
    int findSecondMinimumValue(TreeNode* root) {
        if (root == nullptr) return -1;   // 不存在第二小的情况输出-1

        if (root -> left == nullptr && root -> right == nullptr) return -1;  // 同上
        int i = root -> left -> val;   // 当前节点左子树的值
        int j = root -> right -> val;  // 当前节点右子树的值
        if (i == root -> val) i = findSecondMinimumValue(root -> left);   // 若等于最小值,递归查找左右子树
        if (j == root -> val) j = findSecondMinimumValue(root -> right);  // 右子树递归
        if (i != -1 && j != -1) return min(i, j);  // 第二小是除过根节点之外最小的值。
        if (i != -1) return i;
        return j;
    }

【总结】
二叉树算法设计路线:只管当前节点要做的事,其他抛给递归框架。如果当前节点会对下面的子节点有影响,可以通过辅助函数增长参数列表,借助参数传递信息。
三要素法:
(1)确定递归函数的参数和返回值:明确每次递归的返回值是什么进而确定递归函数的返回类型
(2)确定终止条件:终止条件不写或不对会导致栈溢出的错误。(基本上就是当前遍历的节点为空时本层递归结束)
(3)确定单层递归的逻辑:确定每一层递归需要处理的信息,就是上面说的当前节点要做的事。

二、层序遍历

从左到右一层一层地去遍历二叉树。应用图论中的广度优先遍历。
层序遍历需要借用一个辅助队列来实现,队列先进先出,所以符合一层一层遍历的逻辑。在开始遍历一层的节点时,当前队列中的节点数就是当前层的节点数,只要控制遍历的节点数,就能保证此次遍历的都是当前层的节点。

102. 二叉树的层序遍历

题目描述:
给你二叉树的根节点 root ,返回其节点值的层序遍历 。(即逐层地,从左到右访问所有节点)。

示例:
在这里插入图片描述

代码题解:
之后的层序遍历题目基本套用此框架模板

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;  // 初始化队列que
        if (root != NULL) que.push(root);
        vector<vector<int>> result;  // 初始化二维数组存放结果
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            // 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
            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);
            }
            result.push_back(vec);
        }
        return result;
    }
};

递归方式:

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        int depth = 0;
        order(root, result, depth);
        return result;
    }
    void order(TreeNode* root, vector<vector<int>>& result, int depth) {
        if (root == nullptr) return;
        if (result.size() == depth) result.push_back(vector<int>());
            result[depth].push_back(root -> val);
            order(root -> left, result, depth + 1);
            order(root -> right, result, depth + 1);
    }
};

637. 二叉树的层平均值

题目描述:
给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。

示例:
在这里插入图片描述
在层序遍历的时候每层求总和再取个均值

代码题解:

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*> q;
        if (root != nullptr) q.push(root);
        vector<double> res;
        while (!q.empty()) {
            int size = q.size();
            double sum = 0;
            for (int i = 0; i < size; i++) {
                TreeNode* node = q.front();
                q.pop();
                sum += node -> val;  // 求和
                if (node -> left) q.push(node -> left);
                if (node -> right) q.push(node -> right);
            }
            res.push_back(sum / size);  // 取平均
        }
        return res;
    }
};

429. N 叉树的层序遍历

题目描述:
给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

示例:
在这里插入图片描述
继续延用上面的层序遍历大框架

代码题解:

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        queue<Node *> que;
        if (root != nullptr) que.push(root);
        vector<vector<int>> result;
        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]);
                }
                
            }
            result.push_back(vec);
        }
        return result;
    }
};

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

题目描述:
给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

示例:
在这里插入图片描述
代码题解:

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != nullptr) que.push(root);
        vector<int> result;
        while(!que.empty()) {
            int size = que.size();
            int maxVaule = INT_MIN;    // 用INT_MIN防止下溢 可能有负值出现
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                maxVaule = max(maxVaule, node -> val);
                // 或者maxValue = node->val > maxValue ? node->val : maxValue;
                if (node -> left) que.push(node -> left);
                if (node -> right) que.push(node -> right);
    
            }
            result.push_back(maxVaule);
        }
        return result;
    }
};

513. 找树左下角的值

题目描述:
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。

示例:
在这里插入图片描述
代码题解:

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        vector<int> vec;
        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();
                vec.push_back(node -> val);
                if (node -> right) que.push(node -> right);  // 每层先右后左,那么最后一层最外边的节点就是左下角的值
                if (node -> left) que.push(node -> left);
            }
            
        }
        int s = vec.size();
        return vec[s-1];  // 最后一个元素
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值