题目
给定二叉树,按垂序遍历返回其结点值。
对位于 (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;
}
}