[LeetCode] 每日一题 Day 18:987. 二叉树的垂序遍历

题目

给定二叉树,按垂序遍历返回其结点值。

对位于 (X, Y) 的每个结点而言,其左右子结点分别位于 (X-1, Y-1) 和 (X+1, Y-1)。

把一条垂线从 X = -infinity 移动到 X = +infinity ,每当该垂线与结点接触时,我们按从上到下的顺序报告结点的值( Y 坐标递减)。

如果两个结点位置相同,则首先报告的结点值较小。

按 X 坐标顺序返回非空报告的列表。每个报告都有一个结点值列表。

示例 1:
在这里插入图片描述

输入:[3,9,20,null,null,15,7]
输出:[[9],[3,15],[20],[7]]
解释:
在不丧失其普遍性的情况下,我们可以假设根结点位于 (0, 0):
然后,值为 9 的结点出现在 (-1, -1);
值为 3 和 15 的两个结点分别出现在 (0, 0) 和 (0, -2);
值为 20 的结点出现在 (1, -1);
值为 7 的结点出现在 (2, -2)。

解决

思路
用dfs遍历树把树的节点存下来,因为要根据xy排序,所以肯定是要把xy也一起存下来,可以考虑用多维数组,这里我用的仅仅是一维数组,因为题目中给定了节点的值以及个数的范围,为每个节点设置一个权重weight=100000000*x+10000*y+node.val,用一个int类型存储三种值,需要用哪个再去转换一下就可以:x=weight/100000000, y=weight%100000000/10000, val=weight%10000。这里需要注意这种计算方式需要x和y的值为非负数,所以求x和y的时候要给他们平移到非负数的范围。
代码

class Solution {
    public List<List<Integer>> verticalTraversal(TreeNode root) {
        List<Integer> weight=new ArrayList<Integer>();
        int x=0,y=0,xmin=0;
        xmin=dfs(root,weight,x,y,xmin);
        int n=weight.size();
        for(int k=0;k<n;k++){
            weight.set(k,weight.get(k)+(-1*xmin)*100000000);
        }
        Collections.sort(weight);
        List<List<Integer>> res=new ArrayList();
        int cur=0;
        while(cur<n){
            List<Integer> temp=new ArrayList<Integer>();
            temp.add(weight.get(cur)%100000000);
            while((cur+1)<n && (weight.get(cur)/10000000)==(weight.get(cur+1)/10000000)){
                temp.add((weight.get(cur+1)%100000000));
                cur++;
            }
            Collections.sort(temp);
            for(int j=0;j<temp.size();j++){
                temp.set(j,temp.get(j)%10000);
            }
            res.add(temp);
            cur++;
        }
        return res;
    }
    public int dfs(TreeNode root,List<Integer> weight,int x,int y,int xmin){
        if(root!=null){
            if(xmin>x) xmin=x;
            weight.add((x*100000000+y*10000+root.val));
            int xxmin=Math.min(dfs(root.left,weight,x-1,y+1,xmin),dfs(root.right,weight,x+1,y+1,xmin));
            if(xmin>xxmin) xmin=xxmin;
        }
        return xmin;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值