LeetCode 热题 100 | 二叉树(二)

目录

[1 543. 二叉树的直径](#1 543. 二叉树的直径)

[2 102. 二叉树的层序遍历](#2 102. 二叉树的层序遍历)

[3 108. 将有序数组转换为二叉搜索树](#3 108. 将有序数组转换为二叉搜索树)


菜鸟做题,语言是 C++

1 543. 二叉树的直径

这道题和 124. 二叉树中的最大路径和 太像了

题眼:二叉树的 直径 是指树中任意两个节点之间 最长路径的长度 。

简而言之,就是找出一条路径,且这条路径上的节点最多。

解题思路:

  • 从下往上遍历二叉树
  • 当前子树中的最长路径 = 1 + 左子树中的最长路径 + 右子树中的最长路径
  • 向父节点自荐当前子树中的最长路径 = 1 + max(左子树中的最长路径,右子树中的最长路径)

为什么必须从 "左子树中的最长路径" 和 "右子树中的最长路径" 中选一个?不能都要吗?当然不行。我们要的是一条笔直的路径,如果左右子树都带上,那不就分叉了吗。

思路说明图:

对于绿色节点,在它作为根节点的子树中,最长路径 = 1 + 左子树中的最长路径 + 右子树中的最长路径;绿色节点(左子节点)向蓝色节点(父节点)自荐,自荐的最长路径 = 1 + max(左子树中的最长路径,右子树中的最长路径)。对于蓝色节点,在它作为根节点的子树中,最长路径 = 1 + 左子树中的最长路径 + 右子树中的最长路径。以此类推。

cpp 复制代码
class Solution {
public:
    int ans = 1;
    int helper(TreeNode * root) {
        if (!root) return 0;

        int ltree = helper(root->left);
        int rtree = helper(root->right);
        ans = max(ans, 1 + ltree + rtree);
        return 1 + max(ltree, rtree);
    }

    int diameterOfBinaryTree(TreeNode* root) {
        helper(root);
        return ans - 1;
    }
};

说明:我们算的其实是最多节点数,而路径长度是边的条数,因此需要减一:

cpp 复制代码
return ans - 1;

2 102. 二叉树的层序遍历

是循环,不是递归

**层序遍历:**逐层地,从左到右访问所有节点。

解题思路:

  • 出队:从左到右遍历当前层中的每个节点
  • 入队:将每个节点的左右子节点存入队列中
  • 出队:从左到右遍历左右子节点,即下一层中的每个节点

具体代码:

① 循环条件:当队列中还有节点没有被遍历时,即队列长度不为 0 时。

cpp 复制代码
while (q.size()) {}

② 遍历某一层中的所有节点:

cpp 复制代码
int currentLevelSize = q.size();
for (int i = 0; i < currentLevelSize; ++i) {
    TreeNode * node = q.front();
    q.pop();
    // ...
}

此时队列的大小等于当前层中的节点个数。

③ 存入每个节点的左右子节点,即下一层中的所有节点。

cpp 复制代码
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);

只有节点不为空时才需要被访问。

cpp 复制代码
class Solution {
public:

    vector<vector<int>> levelOrder(TreeNode* root) {
        if (!root) return {};
        vector<vector<int>> ans;
        queue<TreeNode *> q;

        q.push(root);
        while (q.size()) {
            int currentLevelSize = q.size();
            ans.push_back(vector<int> ());
            for (int i = 0; i < currentLevelSize; ++i) {
                TreeNode * node = q.front();
                q.pop();
                ans.back().push_back(node->val);
                if (node->left) q.push(node->left);
                if (node->right) q.push(node->right);
            }
        }

        return ans;
    }
};

3 108. 将有序数组转换为二叉搜索树

与对 105. 从前序与中序遍历序列构造二叉树 的理解有一点点像

可以理解成:将有序数组视为中序遍历的结果,并将其还原回二叉树。

中序遍历的结果数组的特点:(左子树,根节点,右子树)

题眼:高度平衡二叉树 是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。因此,我们每次都取数组区间的中间值为根节点,代码如下:

cpp 复制代码
int mid = (left + right) / 2;

完整代码:

cpp 复制代码
class Solution {
public:

    TreeNode* helper(vector<int>& nums, int left, int right) {
        if (left > right) return nullptr;

        int mid = (left + right) / 2;

        TreeNode* root = new TreeNode(nums[mid]);
        root->left = helper(nums, left, mid - 1);
        root->right = helper(nums, mid + 1, right);
        return root;
    }

    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return helper(nums, 0, nums.size() - 1);
    }
};
相关推荐
jiao_mrswang17 分钟前
leetcode-18-四数之和
算法·leetcode·职场和发展
qystca25 分钟前
洛谷 B3637 最长上升子序列 C语言 记忆化搜索->‘正序‘dp
c语言·开发语言·算法
薯条不要番茄酱26 分钟前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
今天吃饺子31 分钟前
2024年SCI一区最新改进优化算法——四参数自适应生长优化器,MATLAB代码免费获取...
开发语言·算法·matlab
是阿建吖!32 分钟前
【优选算法】二分查找
c++·算法
王燕龙(大卫)36 分钟前
leetcode 数组中第k个最大元素
算法·leetcode
不去幼儿园2 小时前
【MARL】深入理解多智能体近端策略优化(MAPPO)算法与调参
人工智能·python·算法·机器学习·强化学习
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
盼海3 小时前
排序算法(五)--归并排序
数据结构·算法·排序算法
网易独家音乐人Mike Zhou6 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot