首页 > 其他 > 详细

1104. 二叉树寻路

时间:2021-05-08 00:49:32      阅读:24      评论:0      收藏:0      [点我收藏+]

难度 medium
在一棵无限的二叉树上,每个节点都有两个子节点,树中的节点 逐行 依次按 “之” 字形进行标记。

如下图所示,在奇数行(即,第一行、第三行、第五行……)中,按从左到右的顺序进行标记;

而偶数行(即,第二行、第四行、第六行……)中,按从右到左的顺序进行标记。

给你树上某一个节点的标号 label,请你返回从根节点到该标号为 label 节点的路径,该路径是由途经的节点标号所组成的。

示例 1:
技术分享图片

输入:label = 14
输出:[1,3,4,14]
示例 2:

输入:label = 26
输出:[1,2,6,10,26]

提示:

1 <= label <= 10^6

解题思路:这道题目其实没有什么难度,主要就是坐标的关系分析起来比较麻烦,想不到一种简洁优雅的做法,说一下我怎么想的,首先还是找到log2(label),其实就是确定树的深度,记为n,然后用一个数组res记录结果,先把label加进去,然后求这个label在上一层属于哪个节点,这里用label%pow(2, i),i是从n-1到0递减的一个数,就是表示当前在哪一层,用一个变量t = (int) (label % Math.pow(2, i))表示从按递增的顺序来数当前这个数前面有几个数,这里就是 14%pow(2,3)=6,然后用一个变量pos = (int) Math.ceil((double)(t+1) / 2),表示在上一层按数字递减的顺序,当前节点的父节点应该排在第几位,除以2是因为上一层的节点数比这一层少一个,这里就是第4位,因为上一层是按递减的顺序来,所以没有必要分奇偶,这里最简单的就是用起点Math.pow(2, i-1)加长度Math.pow(2, i-1)减去递减的pos位,于是得到新的label,继续网上遍历即可。

代码 t39 s71 java

class Solution {
    public List<Integer> pathInZigZagTree(int label) {
        int n = 0;
        while (Math.pow(2, n)<=label) n++;
        List<Integer> res = new ArrayList<>();
        res.add(label);
        for(int i=n-1; i>0; i--){
            int t = (int) (label % Math.pow(2, i));
            int pos = (int) Math.ceil((double)(t+1) / 2);
            label = (int)(Math.pow(2, i-1)*2 - pos);
            res.add(label);
        }
        Collections.reverse(res);
        return res;
    }
}

解题思路2:这里leecode的题解提供了一种更加清晰严谨的解法,其实思路和我这种差不多,但是把过程都推算得非常详细了,我重新思考了一下,其实解决过程可以更加简化,只要找到规律即可,以14为例,如果我们的二叉树是那种正常从左到右递增的二叉树,上一层的节点应该为14/2=7,但是这里变成了4,主要就是上一层的节点都倒置了,4和7对称,5和6对称,因此我们还是可以用label/2,先找到它原本应该对应的节点,然后再找对称点就可以了,这个对称点在哪里呢?leetcode我参考的那个题解用了很长很长的公式推导,最后得到的结果就是,以第m层为例,label = 3 * Math.pow(2, m) - label/2 - 1,其实可以这样理解,Math.pow(2, m)就是上一层的最小节点,而最大节点应该怎么求呢?每一层的最后一个节点就是2*Math.pow(2, m)-1,因为这一层的最小的节点就是Math.pow(2, m+1),上一层的最大节点肯定比当前层最小节点小一,因此我们把上一层最大和最小节点加起来,就是相互对称的两个数的和,减去label/2,就是label对应的父节点对应的值。代码如下。

代码 t38 s53 java

class Solution {
    public List<Integer> pathInZigZagTree(int label) {
        int n = (int)(Math.log(label) / Math.log(2));
        List<Integer> res = new ArrayList<>();
        res.add(label);
        while(n>0){
            label = (int)(3 * Math.pow(2, --n) - 1 - (label/2));
            res.add(label);
        }
        Collections.reverse(res);
        return res;
    }
}

参考资料:
https://leetcode-cn.com/problems/path-in-zigzag-labelled-binary-tree/solution/jian-dan-yi-dong-de-gong-shi-shi-jian-guo-100-by-a/

1104. 二叉树寻路

原文:https://www.cnblogs.com/zhengxch/p/14742537.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!