首页 > 编程语言 >「代码随想录算法训练营」第十一天 | 二叉树 part1

「代码随想录算法训练营」第十一天 | 二叉树 part1

时间:2024-07-15 17:56:33浏览次数:18  
标签:第十一天 node right TreeNode val 随想录 que 二叉树 left

二叉树的基本知识

链接:https://programmercarl.com/二叉树理论基础.html

要点:

  • 深度优先遍历
    • 前序遍历(递归法,迭代法)
    • 中序遍历(递归法,迭代法)
    • 后序遍历(递归法,迭代法)
  • 广度优先遍历
    • 层次遍历(迭代法)

由于栈就是递归的一种实现结构,因此前中后序遍历的逻辑可以借助栈使用递归的方式来实现。
由于队列先进先出的特点,广度优先遍历一般使用队列来实现。

递归的思想:

每次写递归,要按照三要素去写:

  1. 确定递归函数的参数和返回值。
  2. 确定终止条件。
  3. 确定单层递归的逻辑。

下面开始具体的完成算法题目。

144. 二叉树的前序遍历

题目链接:https://leetcode.cn/problems/binary-tree-preorder-traversal/
题目难度:简单
文章讲解:https://programmercarl.com/二叉树的递归遍历.html
视频讲解:https://www.bilibili.com/video/BV1Wh411S7xt
题目状态:通过

递归思路:

使用递归的三要素完成递归操作,通过代码就可以看明白。

代码实现:

/**
 * 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 traversal(TreeNode *root, vector<int> &res) {
        if(root == nullptr) return;
        res.push_back(root->val);
        traversal(root->left, res);
        traversal(root->right, res);
    }

    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        traversal(root, res);
        return 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<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode *> st;
        vector<int> res;
        if(root == nullptr) return res;
        st.push(root);
        while(!st.empty()) {
            TreeNode *node = st.top();
            st.pop();
            res.push_back(node->val);
            if(node->right) st.push(node->right);
            if(node->left) st.push(node->left);
        }
        return res;
    }
};

145. 二叉树的后序遍历

题目链接:https://leetcode.cn/problems/binary-tree-postorder-traversal/

递归思路和上面一样,甚至代码都不太变,直接看代码:

/**
 * 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 traversal(TreeNode *root, vector<int> &res) {
        if(root == nullptr) return;
        traversal(root->left, res);
        traversal(root->right, res);
        res.push_back(root->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        traversal(root, res);
        return 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<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode *> st;
        vector<int> res;
        if(root == nullptr) return res;
        st.push(root);
        while(!st.empty()) {
            TreeNode *node = st.top();
            st.pop();
            res.push_back(node->val);
            if(node->left) st.push(node->left);
            if(node->right) st.push(node->right);
        }
        reverse(res.begin(), res.end());
        return res;
    }
};

94. 二叉树的中序遍历

题目链接:https://leetcode.cn/problems/binary-tree-inorder-traversal/

递归代码实现:

/**
 * 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 traversal(TreeNode *root, vector<int> &res) {
        if(root == nullptr) return;
        traversal(root->left, res);
        res.push_back(root->val);
        traversal(root->right, res);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        traversal(root, res);
        return 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<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode *> st;
        TreeNode *cur = root;
        while(cur != nullptr || !st.empty()) {
            if(cur != nullptr) {
                st.push(cur);
                cur = cur->left;
            } else {
                cur = st.top();
                st.pop();
                res.push_back(cur->val);
                cur = cur->right;
            }
        }
        return res;
    }
};

102. 二叉树的层序遍历

题目链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/
题目难度:中等
文章讲解:https://programmercarl.com/0102.二叉树的层序遍历.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
题目状态:通过

思路:

利用队列实现层序遍历,并通过size来判断该层是否已经输出完毕,并在输出每一层的某个元素的时候,将该元素的左右孩子压入队列中,直到队列为空,整个循环完毕,层序遍历结束。

代码实现:

/**
 * 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 != nullptr) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            vector<int> vec;
            while(size--) {
                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);
            }
            res.push_back(vec);
        }
        return res;
    }
};

107. 二叉树的层次遍历II

题目链接:https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/
题目难度:中等
文章讲解:https://programmercarl.com/0102.二叉树的层序遍历.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
题目状态:通过

思路:

102.二叉树的层序遍历的思路来,只是在最后反转一下结果即可。

代码实现:

/**
 * 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>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode *> que;
        if(root != nullptr) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            vector<int> vec;
            while(size--) {
                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);
            }
            res.push_back(vec);
        }
        reverse(res.begin(), res.end());
        return res;
    }
};

199. 二叉树的右视图

题目链接:https://leetcode.cn/problems/binary-tree-right-side-view/
题目难度:中等
文章讲解:https://programmercarl.com/0102.二叉树的层序遍历.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
题目状态:通过

个人思路:

同样使用层序遍历,不同的是在每层遍历的时候,只需要把每层最后一个元素的值压入数组中,最后返回这个数组。

代码实现:

/**
 * 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<int> rightSideView(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();
                if(i == size - 1) vec.push_back(node->val);
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }
        return vec;
    }
};

637. 二叉树的层平均值

题目链接:https://leetcode.cn/problems/average-of-levels-in-binary-tree/
题目难度:简单
文章讲解:https://programmercarl.com/0102.二叉树的层序遍历.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
题目状态:通过

个人思路:

依旧是层序遍历,在遍历每一层时记录该层的个数以及该层的和,最后求得平均数,返回在一个数组中。

代码实现:

/**
 * 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<double> averageOfLevels(TreeNode* root) {
        vector<double> res;
        queue<TreeNode *> que;
        if(root != nullptr) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            int len = size;
            double sum = 0; 
            while(size--) {
                TreeNode *node = que.front();
                que.pop();
                sum += node->val;
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            res.push_back(sum / len);
        }
        return res;
    }
};

429. N 叉树的层序遍历

题目链接:https://leetcode.cn/problems/n-ary-tree-level-order-traversal/
题目难度:中等
文章讲解:https://programmercarl.com/0102.二叉树的层序遍历.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
题目状态:通过

个人思路:

加个for循环,将元素的所有孩子都加入队列中。

代码实现:

/*
// 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;
    }
};
*/

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

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

题目链接:https://leetcode.cn/problems/find-largest-value-in-each-tree-row/
题目难度:中等
文章讲解:https://programmercarl.com/0102.二叉树的层序遍历.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
题目状态:通过

个人思路:

加个max,若该层有比max大的元素,该元素的值就是max,最后在数组中存入该层的max即可。

代码实现:

/**
 * 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<int> largestValues(TreeNode* root) {
        queue<TreeNode *> que;
        vector<int> res;
        if(root != nullptr) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            int max = INT_MIN;
            while(size--) {
                TreeNode *node = que.front();
                que.pop();
                max = max > node->val ? max : node->val;
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            res.push_back(max);
        }
        return res;
    }
};

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

题目链接:https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/
题目难度:中等
文章讲解:https://programmercarl.com/0102.二叉树的层序遍历.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
题目状态:通过

个人思路:

定义一个leftmost来存储每层最左边的元素,遍历每层元素时,将leftmostnext指向其后面一个元素,并更新leftmost为当前元素,直到该层遍历完。

代码实现:

/*
// 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;
        Node *leftmost;
        if(root != nullptr) {
            que.push(root);
            leftmost = root;
        }
        while(!que.empty()) {
            int size = que.size();
            for(int i = 0; i < size; ++i) {
                Node *node = que.front();
                que.pop();
                if(i > 0) {
                    leftmost->next = node;
                }
                leftmost = node;
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }
        return root;
    }
};

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

题目链接:https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/
题目难度:中等
文章讲解:https://programmercarl.com/0102.二叉树的层序遍历.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
题目状态:通过

和上一次思路一样,甚至实现代码都一样。

代码实现:

/*
// 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;
        Node *leftmost;
        if(root != nullptr) {
            que.push(root);
            leftmost = root;
        }
        while(!que.empty()) {
            int size = que.size();
            for(int i = 0; i < size; ++i) {
                Node *node = que.front();
                que.pop();
                if(i > 0) {
                    leftmost->next = node;
                }
                leftmost = node;
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }
        return root;
    }
};

104. 二叉树的最大深度

题目链接:https://leetcode.cn/problems/maximum-depth-of-binary-tree/
题目难度:简单
文章讲解:https://programmercarl.com/0102.二叉树的层序遍历.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
题目状态:通过

个人思路:

层序遍历,记录有几层,层数就是二叉树的最大深度。

代码实现:

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

111. 二叉树的最小深度

题目链接:https://leetcode.cn/problems/minimum-depth-of-binary-tree/
题目难度:简单
文章讲解:https://programmercarl.com/0102.二叉树的层序遍历.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
题目状态:通过

思路:

当一个节点既没有左孩子也没有右孩子时,这个节点就是叶子节点,而根结点到叶子节点中间的节点数就是两者之间的高度。

代码实现:

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

标签:第十一天,node,right,TreeNode,val,随想录,que,二叉树,left
From: https://www.cnblogs.com/frontpen/p/18303686

相关文章

  • 代码随想录算法训练营第22天 |二叉树part07:235. 二叉搜索树的最近公共祖先、701.二叉
    代码随想录算法训练营第22天|二叉树part07:235.二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点235.二叉搜索树的最近公共祖先https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/description/代码随想录:htt......
  • 【代码随想录——图论——小岛问题】
    1.水流问题使用两个visited数组即可。1.1DFS版packagemainimport"fmt"vardirection=[][]int{{0,1},{0,-1},{1,0},{-1,0}}funcmain(){ varM,Nint fmt.Scanln(&N,&M) sea:=make([][]int,N) one_visited:=make([][]bool,N) two_visi......
  • Day68 代码随想录打卡|回溯算法篇---子集
    题目(leecodeT78):给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。方法:本题为求子集问题,采用回溯算法解决,与之前的组合与分割问题我们最后收集的是树上的叶子节点不同。子集......
  • 【代码随想录|第十一章 图论part01 | 797.所有可能的路径 】
    代码随想录|第十一章图论part01|图论理论基础,797.所有可能的路径,广搜理论基础一、图论理论基础1.图的基本概念2.图的构造1)邻接矩阵2)邻接表3.图的遍历方式4.深度优先搜索理论基础二、797.所有可能的路径1.核心代码2.问题三、广搜理论基础总结python一、图论理......
  • LeetCode 144. 二叉树的前序遍历
    更多题解尽在https://sugar.matrixlab.dev/algorithm每日更新。组队打卡,更多解法等你一起来参与哦!LeetCode144.二叉树的前序遍历,难度中等。classSolution{publicvoidpreorderTraversal(TreeNoderoot,List<Integer>ans){if(root==null)re......
  • 代码随想录算法训练营第10天|232. 用栈实现队列,225. 用队列实现栈,20. 有效的括号,1047.
    学习任务:Leetcode232.用栈实现队列Leetcode225.用队列实现栈Leetcode20.有效的括号Leetcode1047.删除字符串中的所有相邻重复项Leetcode232.用栈实现队列难度:简单|相关标签:栈、设计、队列题目:请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支......
  • 【数据结构与算法】详解二叉树下:实践篇————通过链式结构深入理解并实现二叉树
          ......
  • Day66 代码随想录打卡|回溯算法篇---分割回文串
    题目(leecodeT131):给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串。返回 s 所有可能的分割方案。方法:本题是一个分割回文串的问题,是回溯算法的另一类问题。针对一个字符串,我们要对其进行分割,并且确保分割后生成的子串也必须全都是回文串。分析回溯三......
  • 代码随想录day 23 组合总和 | 组合总和II | 分割回文串
    组合总和组合总和解题思路利用回溯算法进行遍历,由于数组内的数字可以重复调用,因此在套用模板进行遍历时,下一次递归的startIndex是当前遍历的下标。剪枝操作则是通过比较和是否大于目标值,如果大于则不进行下一次的递归,以此来减少循环遍历的次数,这个条件需要加到for循环中。知......
  • 【代码随想录|回溯算法 77. 组合】
    代码随想录|回溯算法77.组合,216.组合总和III,17.电话号码的字母组合一、77.组合1.核心代码2.输入输出3.问题总结python一、77.组合内容77.组合1.核心代码代码如下(示例):classSolution:defcombine(self,n:int,k:int)->List[List[int]]:......