LeetCode 543. Diameter of Binary Tree 解题笔记

1. 题目描述

https://leetcode.com/problems/diameter-of-binary-tree/#/description

Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.

Example:
Given a binary tree
1
/ \
2 3
/ \
4 5
Return 3, which is the length of the path [4,2,1,3] or [5,2,1,3].

Note: The length of path between two nodes is represented by the number of edges between them.

2. 解题思路

这其实是一道关于二叉树的问题, 一般此类问题都是通过采用递归的思路进行处理,我们可以这样想,其实我们需要求解的所谓的D(diameter)实际上可以这么表示:

D=max(Dleft_child,Dright_child,maxDeepleft+maxDeepright)

也就是说,为了求解这个问题,我们可以将他拆解为3个部分,分别为只包含左子树的子问题 Dleft_child 和 只包含右子树的子问题 Dright_child , 以及经过当前根节点的问题

3. 代码实现

3.1 first version

通过上面给出的思路,我们可以非常容易的给出实现代码:
我们的first-version代码实际上只是简单的将问题使用递归进行处理,由于需要知道子树的深度信息,从而引入了getMaxHeight() 这个递归函数

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int diameterOfBinaryTree(TreeNode* root) {
        if (root == nullptr)
            return 0;
        int leftpart = 0, rightpart = 0, leftheight = 0, rightheight = 0;
        if (root->left){
            leftpart = diameterOfBinaryTree(root->left);
            leftheight = getMaxHeight(root->left);
        }           
        if (root->right){
            rightpart = diameterOfBinaryTree(root->right);
            rightheight = getMaxHeight(root->right);
        }

        return max(max(leftpart, rightpart), leftheight + rightheight);
    }

private:
    int getMaxHeight(TreeNode * root){
        if (root == nullptr)
            return 0;
        int maxHeightLeft = 0, maxHeightRight = 0;
        if (root->left)
            maxHeightLeft = getMaxHeight(root->left);
        if (root->right)
            maxHeightRight = getMaxHeight(root->right);
        return max(maxHeightLeft, maxHeightRight) + 1;
    }
};

运行效果:
这里写图片描述

3.2 second-version

考虑到我们的diameterOfBinaryTree 和 getMaxHeight所实现的特征手段都特别的相像,我们可以考虑将他们合并起来,提高代码运行效率,于是有了如下版本

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int diameterOfBinaryTree(TreeNode* root) {
        return getMaxHeightAndDiameter(root).first;
    }

private:
    pair<int, int> getMaxHeightAndDiameter(TreeNode * root){
        if (root == nullptr)
            return pair<int, int>{0, 0};
        int leftpart = 0, rightpart = 0, leftheight = 0, rightheight = 0;
        if (root->left){
            auto leftPart = getMaxHeightAndDiameter(root->left);
            leftpart = leftPart.first;
            leftheight = leftPart.second;
        }
        if (root->right){
            auto rightPart = getMaxHeightAndDiameter(root->right);
            rightpart = rightPart.first;
            rightheight = rightPart.second;
        }
        return pair<int, int>{max(max(leftpart, rightpart), leftheight + rightheight), 
            max(leftheight, rightheight) + 1};
    }
};

运行效果:
这里写图片描述

4. 参考代码

https://discuss.leetcode.com/topic/83456/java-solution-maxdepth/2
这里采用的基本思想是这样的:
实际上对于每一个节点我们都可以计算以他为根节点的diameter的长度,那么我们只需要在这个过程中,挑选得到长度最长的那个diameter就可以了
可以发现这个参考代码,思想炒鸡简单。。。

public class Solution {
    int max = 0;

    public int diameterOfBinaryTree(TreeNode root) {
        maxDepth(root);
        return max;
    }

    private int maxDepth(TreeNode root) {
        if (root == null) return 0;        
        int left = maxDepth(root.left);
        int right = maxDepth(root.right);        
        max = Math.max(max, left + right);        
        return Math.max(left, right) + 1;
    }
}

5. 一些关于二叉树的常用函数

5.1 构建二叉树

在做oj的过程中,我们经常遇到二叉树这类问题,由于手工构建一个二叉树进行测试非常费劲,于是为了偷懒,我们编写了如下函数用于自动构建二叉树:

TreeNode * createTreeByString(istringstream & iss){
    string line;
    getline(iss, line, '#');
    if (line == "!" || line == "")
        return nullptr;

    TreeNode * root = new TreeNode(stoi(line));
    root->left = createTreeByString(iss);
    root->right = createTreeByString(iss);
    return root;    
}

实际上这是借助了先序遍历的思想进行编写,其输入的形式如下:

    istringstream iss("1#2#4#!#!#5#!#!#3#!#!#");
    auto root = createTreeByString(iss);

5.2 中序遍历二叉树

我们同时也编写了一个中序遍历二叉树的函数,用来测试上述函数

void inorder(TreeNode * root, ostringstream & oss){
    if (root){
        inorder(root->left, oss);
        oss << root->val << " ";
        inorder(root->right, oss);
    }
}

通过oss.str()方法可以获取得到相应的字符串表示形式
测试代码如下:

TEST(createTreeByString, createTree){
    istringstream iss("1#2#4#!#!#5#!#!#3#!#!#");
    auto root = createTreeByString(iss);
    ostringstream oss;
    inorder(root, oss);
    string inorder_result = oss.str();
    EXPECT_EQ(inorder_result, string("4 2 5 1 3 "));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值