代码随想录算法训练营三期 day 15 - 二叉树(2)

二叉树的层序遍历

原文链接:二叉树的层序遍历
题目链接:102. 二叉树的层序遍历
107. 二叉树的层序遍历 II
199. 二叉树的右视图
637.二叉树的层平均值
429. N 叉树的层序遍历
515. 在每个树行中找最大值
116. 填充每个节点的下一个右侧节点指针
117. 填充每个节点的下一个右侧节点指针 II
104. 二叉树的最大深度
111. 二叉树的最小深度
视频链接:讲透二叉树的层序遍历 | 广度优先搜索 | LeetCode:102.二叉树的层序遍历

102. 二叉树的层序遍历

分析:
借助一个队列保存每一层例遍历过的元素;
二维数组 r e s res res 存放最终结果;
(1) 若根结点不为空,则将其加入到队列中;
(2) 循环直至队列为空:
设置一个 s i z e size size 记录当前层结点的个数(控制队列里面弹出结点的数量,因为队列里可能包含两层的元素), 一维数组 v e c vec vec 存储每层结点的值;
循环 s i z e size size 次:
i. 取每个结点并把它们的值存放到一维数组 v e c vec vec 中,并将其弹出队列;
ii. 若左右孩子不为空,则将它们加入到队列中(体现出了 s i z e size size 的作用);

~循环结束
v e c vec vec 加入到 r e s res res 中;
~循环结束
代码如下:

/**
 * 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) {
        vector<vector<int>> res;
        queue<TreeNode*> que;
        if (root != NULL) {
            que.push(root);
        }
        while (!que.empty()) {
            vector<int> vec;
            int size = que.size();
            while (size--) {
                TreeNode* cur = que.front();
                que.pop();
                vec.push_back(cur -> val);
                if (cur -> left) {
                    que.push(cur -> left);
                }
                if (cur -> right) {
                    que.push(cur -> right);
                }
            }
            res.push_back(vec);
        }
        return res;
    }
};

107. 二叉树的层序遍历 II

最后把 r e s res res 数组反转一下即可:

reverse(res.begin(), res.end()); // 在这里反转一下数组即可

199. 二叉树的右视图

层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进 r e s res res 数组中,随后返回 r e s res res 就可以了。

if (i == (size - 1)) res.push_back(cur -> val); // 将每一层的最后元素放入result数组中

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

本题依然是层序遍历,只不过在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点就可以了。

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

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

104. 二叉树的最大深度

最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。

/**
 * 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;
        int depth = 0;
        if (root == NULL) {
            return 0;
        }
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            depth++;
            while (size--) {
                TreeNode* cur = que.front();
                que.pop();
                if (cur -> left) {
                    que.push(cur -> left);
                }
                if (cur -> right) {
                    que.push(cur -> right);
                }
            }
        }
        return depth;
    }
};

111. 二叉树的最小深度

相对于 104. 二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。
需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点:

/**
 * 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;
        int depth = 0;
        if (root == NULL) {
            return 0;
        }
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            depth++;
            for (int i = 0; i < size; i++) {
                TreeNode* 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 depth;
                }
            }
        }
        return depth;
    }
};

翻转二叉树

原文链接:226. 翻转二叉树
题目链接:226. 翻转二叉树
视频链接:听说一位巨佬面Google被拒了,因为没写出翻转二叉树 | LeetCode:226.翻转二叉树
前序遍历
递归三部曲:
(1) 确定递归函数参数及返回值;
参数:要传入的结点的指针; 返回值: T r e e N o d e ∗ TreeNode* TreeNode;
(2) 终止条件: 结点为空的时候返回;
(3) 单层递归逻辑:
先进行交换左右孩子结点,然后反转左子树,反转右子树;

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

对称二叉树

原文链接:101. 对称二叉树
题目链接:101. 对称二叉树
视频链接:新学期要从学习二叉树开始! | LeetCode:101. 对称二叉树
本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。但都可以理解算是后序遍历,尽管已经不是严格上在一个树上进行遍历的后序遍历了。
递归三部曲:
(1) 确定递归函数的参数和返回值
因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。返回值自然是 bool 类型。
(2) 确定终止条件
节点为空的情况有:
左为空,右不为空,不对称, r e t u r n   f a l s e ; return\ false; return false;
左不为空,右为空,不对称, r e t u r n   f a l s e ; return\ false; return false;
左右都为空,对称, r e t u r n   t r u e ; return\ true; return true;
此时已经排除掉了 节点为空 的情况,那么剩下的就是 左右节点不为空;
左右都不为空,比较节点数值,不相同就 r e t u r n   f a l s e ; return\ false; return false;
此时 左右节点不为空,且 数值不相同 的情况我们也处理了。
(3) 单层递归逻辑
此时才进入单层递归的逻辑,单层递归的逻辑就是处理 左右节点都不为空,且数值相同 的情况。
比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子
比较内侧是否对称,传入左节点的右孩子,右节点的左孩子
如果左右都对称就返回 t r u e true true ,有一侧不对称就返回 f a l s e false false

/**
 * 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 {
private:
    bool compare(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 outside = compare(left -> left, right -> right);
        bool inside = compare(left -> right, right -> left);
        return outside && inside;
    }

public:
    bool isSymmetric(TreeNode* root) {
        if (root == NULL) {
            return true;
        }
        return compare(root -> left, root -> right);
    }
};

你可能感兴趣的:(Algorithms,算法,leetcode)