二叉树直径

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 

/ \ 
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)
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 "));
}


原文地址:

https://blog.csdn.net/zhyh1435589631/article/details/65939602

posted @ 2019-03-29 09:29  wang-shishuang  阅读(185)  评论(0编辑  收藏  举报