IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 代码随想录算法训练营第十五天|102. 二叉树的层序遍历、226. 翻转二叉树、101. 对称二叉树 -> 正文阅读

[数据结构与算法]代码随想录算法训练营第十五天|102. 二叉树的层序遍历、226. 翻转二叉树、101. 对称二叉树

LeetCode?102. 二叉树的层序遍历

链接:102. 二叉树的层序遍历

思路:

层序遍历为从左到右,从上到下依次遍历二叉树的节点,可以采用BFS(广度优先搜索)的方式。实现BFS算法需要使用队列这一数据结构。首先把根节点压入队列,每经过一层,会弹出当前层的节点,并把下一层的所有子节点压入队列,所以在到达下一层的时候,队列的大小会始终等于这一层的节点数。用一个循环把该层的所有节点都push进一个数组,并在循环结束的时候把该数组push到另一个由数组组成的数组里,即可得到二叉树的层序遍历。

代码:

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> myQueue;
        vector<vector<int>> ans;
        if (root == nullptr)
            return ans;
        myQueue.push(root);
        while (!myQueue.empty())
        {
            // 获取每一层的节点个数
            int size = myQueue.size();
            // 把每一层的节点都放进数组
            vector<int> tmp;
            for (int i = 0; i < size; i++)
            {
                TreeNode *node = myQueue.front();
                myQueue.pop();
                if (node->left)
                    myQueue.push(node->left);
                if (node->right)
                    myQueue.push(node->right);
                tmp.push_back(node->val);

            }
            ans.push_back(tmp);
        }
        return ans;
    }
};

时间复杂度:O(n)

空间复杂度:O(n)

使用层序遍历可以一下子解决很多相似的问题,只需要稍微改几行代码即可。

LeetCode?107. 二叉树的层序遍历 II

107. 二叉树的层序遍历 II

完全一样的代码,只不过是自底向上的,所以只需要在遍历结束后反转一下数组即可

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

LeetCode?199. 二叉树的右视图

199. 二叉树的右视图

只需要在遍历每层的时候把最后一个元素压入数组即可

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        queue<TreeNode*> myQueue;
        vector<int> ans;
        if (root == nullptr)
            return ans;
        myQueue.push(root);
        while (!myQueue.empty())
        {
            int size = myQueue.size();

            for (int i = 0; i < size; i++)
            {
                TreeNode *node = myQueue.front();
                myQueue.pop();
                if (node->left)
                    myQueue.push(node->left);
                if (node->right)
                    myQueue.push(node->right);
                // 把每层最右边的元素放入数组
                if (i == size - 1)
                    ans.push_back(node->val);
            }
        }
        return ans;
    }
};

LeetCode?637. 二叉树的层平均值

637. 二叉树的层平均值

遍历每层的时候计算该层节点值的和,然后压入数组时求一下平均数即可

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*> myQueue;
        vector<double> ans;
        if (root == nullptr)
            return ans;
        myQueue.push(root);
        while (!myQueue.empty())
        {
            // 获取每一层的节点个数
            int size = myQueue.size();
            double sum = 0;
            for (int i = 0; i < size; i++)
            {
                TreeNode *node = myQueue.front();
                myQueue.pop();
                if (node->left)
                    myQueue.push(node->left);
                if (node->right)
                    myQueue.push(node->right);
                sum += node->val;

            }
            ans.push_back((double)sum / size);
        }
        return ans;
    }
};

LeetCode 429.N叉树的层序遍历

429. N 叉树的层序遍历

唯一的区别是压入队列的时候用的是一个数组

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        queue<Node*> myQueue;
        vector<vector<int>> ans;
        if (root == nullptr)
            return ans;
        myQueue.push(root);
        while (!myQueue.empty())
        {
            // 获取每一层的节点个数
            int size = myQueue.size();
            // 把每一层的节点都放进数组
            vector<int> tmp;
            for (int i = 0; i < size; i++)
            {
                Node *node = myQueue.front();
                myQueue.pop();
                for (Node* node : node->children)
                {
                    if (node)
                        myQueue.push(node);
                }
                tmp.push_back(node->val);

            }
            ans.push_back(tmp);
        }
        return ans;
    }
};

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

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

更简单,记录一下最大值就可以了,唯一要注意的是int的精度问题

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        queue<TreeNode*> myQueue;
        vector<int> ans;
        if (root == nullptr)
            return ans;
        myQueue.push(root);
        while (!myQueue.empty())
        {
            // 获取每一层的节点个数
            int size = myQueue.size();
            int max = INT_MIN;
            for (int i = 0; i < size; i++)
            {
                TreeNode *node = myQueue.front();
                myQueue.pop();
                if (node->left)
                    myQueue.push(node->left);
                if (node->right)
                    myQueue.push(node->right);
                if (max < node->val)
                    max = node->val;
            }
            ans.push_back(max);
        }
        return ans;
    }
};

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

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

在每层把前size-1个节点加入next指针

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> myQueue;
        if (root == nullptr)
            return root;
        myQueue.push(root);
        while (!myQueue.empty())
        {
            // 获取每一层的节点个数
            int size = myQueue.size();
            for (int i = 0; i < size; i++)
            {
                Node *node = myQueue.front();
                myQueue.pop();
                // 给前size-1个节点加入next指针
                if (i < size - 1)
                    node->next = myQueue.front();

                if (node->left)
                    myQueue.push(node->left);
                if (node->right)
                    myQueue.push(node->right);
            }
        }
        return root; 
    }
};

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

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

同上代码无任何区别

LeetCode?104. 二叉树的最大深度

104. 二叉树的最大深度

每经过一层就depth++最后返回depth即可

class Solution {
public:
    int maxDepth(TreeNode* root) {
        queue<TreeNode*> myQueue;
        if (root == nullptr)
            return 0;
        myQueue.push(root);
        int depth = 0;
        while (!myQueue.empty())
        {
            // 获取每一层的节点个数
            int size = myQueue.size();
            for (int i = 0; i < size; i++)
            {
                TreeNode *node = myQueue.front();
                myQueue.pop();
                if (node->left)
                    myQueue.push(node->left);
                if (node->right)
                    myQueue.push(node->right);
            }
            depth++;
        }
        return depth;
    }
};

LeetCode?111. 二叉树的最小深度

111. 二叉树的最小深度

稍微有点不同的是增加一个判断node->left和node->right的条件,如果两个指针都为空则直接返回depth

class Solution {
public:
    int minDepth(TreeNode* root) {
        queue<TreeNode*> myQueue;
        if (root == nullptr)
            return 0;
        myQueue.push(root);
        int depth = 0;
        while (!myQueue.empty())
        {
            // 获取每一层的节点个数
            int size = myQueue.size();
            depth++;
            for (int i = 0; i < size; i++)
            {
                TreeNode *node = myQueue.front();
                myQueue.pop();
                if (node->left)
                    myQueue.push(node->left);
                if (node->right)
                    myQueue.push(node->right);
                 // 当左右孩子都为空的时候,说明是最低点的一层了,退出
                if (!node->left && !node->right)
                    return depth;
            }
        }
        return depth;
    }
};

LeetCode?226. 翻转二叉树

链接:226. 翻转二叉树

递归法:

思路:

用前序遍历或者后续遍历的方式,反转left和right两个节点的指针即可。

代码:

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

迭代法:

思路:

按照迭代法写前序遍历的思路,需要操作的时候交换两个指针即可。

代码:

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == nullptr)
            return root;
        stack<TreeNode*> myStack;
        myStack.push(root);
        while (!myStack.empty())
        {
            TreeNode* node = myStack.top();
            myStack.pop();
            if (node->right)
                myStack.push(node->right);
            if (node->left)
                myStack.push(node->left);
            swap(node->left, node->right);
        }
        return root;
    }
};

LeetCode?101. 对称二叉树

链接:101. 对称二叉树

递归法:

思路:

该题同样用了递归法和迭代法两种思路,不过大体思路还是一致的。判断一个二叉树是否对称,实际上就是判断根节点下的两个子树是否是对称的。左子树和右子树同时用后续遍历,只不过左子树遍历方式为左右中,右子树的遍历方式改为右左中,这样两个子树遍历的节点正好是对称的,只要每次对比两个节点是否一样即可。

对比两个节点是否一样需要考虑多种情况。首先要判断两个节点是否为空,如果其中一个为空另一个不为空,则返回false。如果两个都为空,则返回true。如果两个都不为空,则比较两个节点的值是否一致,如不一致则返回false。最后要考虑两个节点的值一致的情况,在左右节点一致时递归调用函数检查它们的子节点是否也是对称的。

代码:

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        return dfs(root->left, root->right);
    }
    bool dfs(TreeNode* leftNode, TreeNode* rightNode)
    {
        if (leftNode == nullptr && rightNode != nullptr) return false;
        else if (leftNode != nullptr && rightNode == nullptr) return false;
        else if (leftNode == nullptr && rightNode == nullptr) return true;
        else if (leftNode->val != rightNode->val) return false;
        if (dfs(leftNode->left, rightNode->right) && dfs(leftNode->right, rightNode->left))
            return true;
        else
            return false;
    }
};

迭代法:

思路:

迭代法采用了层序遍历,但和层序遍历并不完全相同,而是在每一层同时pop左子树和右子树两个节点,并判断这两个节点是否相同。判断条件和递归法的方式基本相同,不同点则是在两个节点相同的时候,在这里需要同时把左节点的两个子节点和右节点的两个子节点按配对放入队列,左子树的左节点对应右子树的右节点,反之也是一样的,这样在下次同时pop出来的两个左右子节点也是对应的。

代码:

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        queue<TreeNode*> myQueue;
        myQueue.push(root->left);
        myQueue.push(root->right);
        while (!myQueue.empty())
        {
            TreeNode *left = myQueue.front();myQueue.pop();
            TreeNode *right = myQueue.front();myQueue.pop();
            if (left != nullptr && right == nullptr)
                return false;
            else if (left == nullptr && right != nullptr)
                return false;
            else if (left != nullptr && right != nullptr && left->val != right->val)
                return false;
            else if (left != nullptr && right != nullptr && left->val == right->val)
            {
                myQueue.push(left->left);
                myQueue.push(right->right);
                myQueue.push(left->right);
                myQueue.push(right->left);
            }
        }
        return true;
    }
};

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:25:10  更:2022-10-31 12:27:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:17:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码