二叉树每个结点均有权值,设计一个算法算出权值最大的叶节点到权值最小的叶节点的距离

二叉树

(网易2016实习Java研发工程师编程题)

题目描述

有一棵二叉树,树上每个点标有权值,权值各不相同,请设计一个算法算出权值最大的叶节点权值最小的叶节点距离。二叉树每条边的距离为1,一个节点经过多少条边到达另一个节点为这两个节点之间的距离。

给定二叉树的根节点root,请返回所求距离。

解法一:利用二进制编码



//典型的二进制编码题,算出叶子节点二进制编码,再比编码,计算后缀长度和
import java.util.*;
 
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}*/
 
public class Tree {
    private int max=0;
    private int min=99999;
    private StringBuilder maxcodec;
    private StringBuilder mincodec;
        void PreOrder(TreeNode T,char code,StringBuilder codec){
        if(T!=null){           
            codec.append(code);
            if(T.left==null && T.right==null)
            {
                if(max<T.val)
                {
                    max=T.val;
                    maxcodec = codec;
                }
                 
                if(min>T.val)
                {
                    min=T.val;
                    mincodec = codec;
                }
            }
            PreOrder(T.left,'0',new StringBuilder(codec));
            PreOrder(T.right,'1',new StringBuilder(codec));
        }
    }
    public int getDis(TreeNode root) {
        PreOrder(root,'0',new StringBuilder());
        int index=0;
        for(index=0; index<(maxcodec.length()>mincodec.length()?maxcodec.length():mincodec.length());index++)
        {
            if(maxcodec.charAt(index)!=mincodec.charAt(index))
                break;
        }
        return (maxcodec.substring(index).length()+mincodec.substring(index).length());
     
        // write code here
    }
}

解法二:


import java.util.*;
/*
 
public class TreeNode {
 
int val = 0;
 
TreeNode left = null;
 
TreeNode right = null;
 
public TreeNode(int val) {
 
this.val = val;
 
}
 
}*/
 
public class Tree {
 
private TreeNode maxNode = new TreeNode(Integer.MIN_VALUE);
 
private TreeNode minNode = new TreeNode(Integer.MAX_VALUE);
 
 
 
public int getDis(TreeNode root) {
 
    // write code here
 
    getMaxMin(root);//找到最大最小叶子节点
 
    TreeNode lcaNode = getLCA(root);//找LCA
 
    int a = getNodeDis(lcaNode, maxNode);//最大值叶子节点到LCA的距离;
 
    int b = getNodeDis(lcaNode, minNode);//最小值叶子节点到LCA的距离;
 
    return a+b;
 
}
 
 
 
// 先找到最大最小叶子节点
 
public void getMaxMin(TreeNode root) {
 
    if (root == null) {
 
        return;
 
    }
 
    if (root.left == null && root.right == null) {
 
        if (root.val > maxNode.val) {
 
            maxNode = root;
 
        } else if (root.val < minNode.val) {
 
            minNode = root;
 
        }
 
    }
 
    getMaxMin(root.left);
 
    getMaxMin(root.right);
 
}
 
 
 
// LCA最近公共祖先
 
public TreeNode getLCA(TreeNode root) {
 
    if (root == null) {// 说明是空树
 
        return null;
 
    }
 
    if (root.val == maxNode.val || root.val == minNode.val) {// 在当前树的根节点上找到两个节点之一
 
        return root;
 
    }
 
    TreeNode leftNode = getLCA(root.left);// 左子树中的查找两个节点并返回查找结果
 
    TreeNode rightNode = getLCA(root.right);// 右子树中查找两个节点并返回查找结果
 
    if (leftNode == null) {// 左子树中没找到,则一定在右子树上
 
        return rightNode;
 
    } else if (rightNode == null) {// 右子树没找到一定在左子树上
 
        return leftNode;
 
    } else {// 左右子树均找到一个节点,则根节点为最近公共祖先
 
        return root;
 
    }
 
}
 
 
 
//获取叶子节点到LCA距离
 
public int getNodeDis(TreeNode lcaNode, TreeNode node){
 
    if(lcaNode==null){
 
        return -1;
 
    }
 
    if(lcaNode.val==node.val){
 
         return 0;
 
    }
 
    //三种情况:两个均在左子树;两个均在右子树;一左一右,所以不能用if-elseif结构
 
    int distance = getNodeDis(lcaNode.left, node);//左子树未找到两个节点之一
 
    if(distance==-1){
 
        distance = getNodeDis(lcaNode.right, node);
 
    }
 
    if(distance!=-1){
 
        return distance+1;
 
    }
    return -1;
	}
}

链接:https://www.nowcoder.com/questionTerminal/d567727f21a247f7b64ba32431cb9a19?f=discussion
来源:牛客网

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 根据给出的条件,我们可以将节点权值从小到大排序为:10,12,16,21,30。 接下来,我们可以根据哈夫曼编码的规则来构造哈夫曼树。 首先,我们找到权值最小的两个节点,将它们合并成一个新的节点,其权值为它们的和,即10+12=22。然后,我们将这个新节点插入到原来的节点的位置上,得到以下的树形结构: ``` 22 / \ 10 12 / \ 16 21 / 30 ``` 接下来,我们再次找到权值最小的两个节点,将它们合并成一个新的节点,其权值为它们的和,即16+21=37。然后,我们将这个新节点插入到原来的节点的位置上,得到以下的树形结构: ``` 59 / \ 22 37 / \ / \ 10 12 16 21 / 30 ``` 重复上述步骤,直到所有的节点都被合并为一个节点。最终得到的哈夫曼树如下: ``` 118 / \ / \ / \ / \ / \ / \ 59 59 / \ / \ 22 37 22 37 / \ / \ / \ / \ 10 12 16 21 16 21 30 10 ``` 最小带权路径长度(WPL)定义为节点权值与其到根节点的路径长度的乘积之和。因此,我们可以计算出最小带权路径长度为: ``` WPL = 10*3 + 12*3 + 16*4 + 21*4 + 30*4 = 226 ``` 因此,该二叉树的带权路径长度为226,即最小带权路径长度为226。 ### 回答2: 首先需要了解什么是二叉树的带权路径长度(wpl):指二叉树中每一个叶子结点权值乘上它到根结点的路径长度之和,即以叶子结点权值的权路径长度之和。最小的带权路径长度指该二叉树中,最优解中的权值和。 根据哈夫曼编码的思想,可以利用贪心算法来求解带权路径长度的最小值。 步骤如下: 1. 根据给定的权值构建哈夫曼树(哈夫曼树是带权路径长度最短的树),将最小的两个权值相加,作为它们共同的父节点权值,重复此过程直至构建出哈夫曼树。 2. 对于每一次的合并操作,都要计算该节点的带权路径长度,即它的权值乘以它到根节点距离。对每个节点的带权路径长度进行累加,得到该二叉树的带权路径长度。 3. 计算出二叉树的带权路径长度之和,即为该二叉树最小带权路径长度。 由给定的权值构建出哈夫曼树如下图: 105 / \ 46 59 / \ / \ 21 25 30 29 \ / \ 10 16 13 在哈夫曼树中,所有叶子结点的带权路径长度之和即为最小的带权路径长度。所以5个节点权值乘以它们到根节点距离分别为: 10 * 3 + 12 * 3 + 16 * 2 + 21 * 2 + 30 * 2 = 226 因此,最小带权路径长度为 226。 ### 回答3: 根据哈夫曼树的构造方法,我们可以先将这 5 个节点按照权值从小到大排序,得到序列 10、12、16、21、30。接下来根据哈夫曼树的构造规则,我们在每一次构造的过程中,都会选择两个权值最小节点进行合并,形成一个新的节点,其权值为两个节点权值之和。因此,我们可以模拟构造哈夫曼树的过程,具体步骤如下: 1. 选择权值最小的两个节点 10 和 12,将它们合并为一个节点权值为 22,得到以下树形结构: 22 / \ 10 12 2. 选择权值最小的两个节点 16 和 21,将它们合并为一个节点权值为 37,得到以下树形结构: 22 37 / \ / \ 10 12 16 21 3. 最后,将上一步得到的两个子树合并为一个树,得到以下树形结构: 95 ______|______ | | 37 58 ___|___ ___|___ | | | | 16 21 22 30 最终得到的树就是哈夫曼树,其带权路径长度为: 10 × 2 + 12 × 2 + 16 × 2 + 21 × 2 + 30 × 1 = 118 因此,这个二叉树最小带权路径长度为 118。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值