尝试使用两个if语句打印树的顶视图

时间:2015-07-13 14:04:28

标签: java data-structures tree treeview binary-tree

问题陈述

您将获得指向二叉树根的指针。打印二叉树的顶视图。 您只需要完成该功能。

我的代码:

void top_view(Node root)
 {  
       Node r = root;

       if(r.left!=null){
          top_view(r.left);
          System.out.print(r.data + " ");
        }
       if(r.right!=null){
          System.out.print(r.data + " ");
          top_view(r.right);
        }
}

每次调用函数时都会执行两个if语句,但我只需要执行其中一个。我尝试过切换但是它给出了常量表达式错误。我已经为这个问题找到了不同的解决方案。

所以我只想知道,如果一次执行,我们是否只能制作一个,即有没有办法修改我的代码而不改变方法?

enter image description here enter image description here

问题链接: https://www.hackerrank.com/challenges/tree-top-view

17 个答案:

答案 0 :(得分:7)

您的方法不会有效,因为当您致电leftright子树时,您只会坚持下去。这种方法的问题在于你只是首先调用树的哪一侧。

可能你可以通过使用堆栈和队列来解决它,就像其他人说的那样但我觉得以下是一种更简单,更直观的方法:

(最后看到代码,非常简单)

解决此问题的方法是从root用户维护horizontal distance,然后为每个不同的horizontal distance打印第一个节点。

什么是水平距离?

我只是拍摄你添加的图像。

enter image description here

特定Horizontal distance

node定义为从根水平的数量。如果你看到没有边缘会变成垂直距离。

为了让根目录左侧的所有节点更容易,以-ve水平距离和右侧正距离开始。

如何计算水平距离?

如果你向右走add 1,如果你要离开,请添加-1

所以

    horizontal distance of 3 = 0

    horizontal distance of 5 = -1
    horizontal distance of 1 = -2
    horizontal distance of 9 = -1
    horizontal distance of 4 = 0

    horizontal distance of 2 =  1
    horizontal distance of 6 =  0
    horizontal distance of 7 =  2
    horizontal distance of 8 =  0

节点3,4,6,8的水平距离相同0是什么意思?

这意味着当你从顶部看到所有这些节点在它上面的垂直线上时。

如果它们垂直排成一行你看到了什么?

可以从root首先到达。

您如何找到可以首先到达哪一个?

像往常一样 BFS

如何为您的示例打印解决方案?

有五种不同的水平距离值{-1,-2,0,1,2}

hor dist        Nodes

   0      - {3,6,8} // 3 comes first in BFS so print 3
  -1      - {5,9}   // 5 comes first in BFS so print 5
  -2      - {1}     // just print 1
   1      - {2}     // just print 2
   2      - {7}     // just print 7

所以它会打印{3,5,1,2,7}

HashSet<Integer> set = new HashSet<>();
Queue<QueueItem> queue = new LinkedList<>();
queue.add(new QueueItem(root, 0)); // Horizontal distance of root is 0

while (!queue.isEmpty())
{
    QueueItem temp = queue.poll();
    int hd = temp.hd;
    TreeNode n = temp.node;

    // If this is the first node at its horizontal distance,
    // then this node is in top view
    if (!set.contains(hd))
    {
        set.add(hd);
        System.out.print(n.key + " ");
    }

    if (n.left != null)
        queue.add(new QueueItem(n.left, hd-1));
    if (n.right != null)
        queue.add(new QueueItem(n.right, hd+1));
}

答案 1 :(得分:2)

使用以下方法可以很容易地解决这个问题:

堆栈:打印根和左子树。

队列:打印正确的子树。

你的功能应该是这样的:

 void topview(Node root)
 {
     if(root==null)
      return;
     Stack<Integer> s=new Stack<Integer>();
     s.push(root.data);
     Node root2=root;
     while(root.left!=null)
     {
      s.push(root.left.data);
      root=root.left;
     }
     while(s.size()!=0)
      System.out.print(s.pop()+" ");

     Queue<Integer> q=new LinkedList<Integer>(); 
     q.add(root2.right.data);
     root2=root2.right;     
     while(root2.right!=null)
     {
      q.add(root2.right.data);
      root2=root2.right;
     }
     while(q.size()!=0)
      System.out.print(q.poll()+" ");
 }

答案 2 :(得分:1)

这个实际上有效。不需要队列,但是使用堆栈从左侧回溯,因为我们没有引用父级。

void top_view(Node root)
{
    Stack<Node> p = new Stack<Node>();
    Node current = root;
    while (current != null) 
    {
        p.push(current);
        current = current.left;
    }

    while (p.peek() != root) 
    {
        System.out.print(p.pop().data + " ");
    }

    current = root;
    while (current != null) 
    {
        System.out.print(current.data + " ");
        current = current.right;
    }
}

答案 3 :(得分:0)

以上某些答案无效。我曾尝试对它们发表评论,但是很显然,我的评分不正确,因为我之前从未尝试在此处发表评论。

问题是您需要对树进行广度优先搜索,以确保节点的正确顺序。为了排除“模糊”节点,另一个网站建议对每个节点进行排名。根为0。节点左侧的所有分支的父级为-1。右边的所有分支的父级为+1。祖先等级重复的所有节点都将被排除。

然后按等级顺序打印出选定的节点。在所有情况下都可以使用。

答案 4 :(得分:0)

def printTopView(root):

lst=[]
current1=root.left
while current1!=None:
    lst.append(current1.key)
    current1=current1.left
lst.reverse()
current2=root
while current2!=None:
    lst.append(current2.key)
    current2=current2.right

print(*lst)

答案 5 :(得分:0)

Python解决方案

def topView(root):
    q = deque()
    #Adding root node to the deque along with its Horizontal Distance from root.
    q.append([root,0])
    
    #Dictionary to store the {Horizontal Distance: First Node that has this distance}
    s = {}
    
    #Breadth First Traversal - [To keep track of the first Node that is visited.]
    while q:
        temp = q.popleft()
        #Horizontal Distance from Root
        d = temp[1]
        
        #Adding the Left Child to the Queue (if Exists)
        if temp[0].left is not None:
            q.append([temp[0].left, d-1])
        
        #Adding the Right Child to the Queue (if Exists)
        if temp[0].right is not None:
            q.append([temp[0].right, d+1])
        
        #Adding the Horizontal Distance and the First Node that has this distance to Dictionary.
        if d not in s:
            s[d] = temp[0].info
    
    #Printing out the Top View of Tree based on the values in the Dictionary - From least to Highest Horizontal Distance from Root Node.
    for i in sorted(s):
        print(s[i], end=" ")

答案 6 :(得分:0)

此:

for loops

一直是适用于Python的解决方案,但由于某些原因,它在hackerrank.com上的7个测试案例中有6个失败。有人可以解释一下为什么会这样吗?

那些只运行“向左”和“向右”功能的人不了解任务。

答案 7 :(得分:0)

可以在此处找到解决方案 - Git hub URL

请注意,无论hackerrank问题是关于平衡树,如果树处于不平衡状态,如下所示

 "Sending email to the following rbrown at email address $rbrownEmail

对于这些类型的树,需要一些复杂的逻辑,这在geeksforgeeks中定义 - GeeksforGeeks

答案 8 :(得分:0)

最简单的递归解决方案

void top_view(Node root)
{
 // For left side of the tree
    top_view_left(root);
 // For Right side of the tree
    top_view_right(root.right);
}

void top_view_left(Node root){
     if(root != null)
  {     
     // Postorder
     top_view_left(root.left);
     System.out.print(root.data + " ");
  }  
}

void top_view_right(Node root){
    if(root != null)
  {
        //  Preorder
      System.out.print(root.data + " ");
      top_view_right(root.right);
  }  
}

答案 9 :(得分:0)

这是c ++中二叉树顶视图的代码..

void topview(node * root,queue&amp; Q)

{

if(!root)
    return;
map<int,int> TV;
Q.push(root);
TV[root->data]=0;
map<int,int>:: iterator it;
int min=INT_MAX,max=INT_MIN;
while(!Q.empty())
{
    node* temp =Q.front();
    Q.pop();
    int l=0;

    for(it=TV.begin();it!=TV.end();it++)
    {
        if(it->first==temp->data)
        {
            l=it->second;
           break;
        }

    }
    if(l<min) 
        {min=l;}
    if(l>max) 
        max=l;
    if(temp->left)
    {
        Q.push(temp->left);
        TV[temp->left->data] = l-1;
    }
    if(temp->right)
    {
        Q.push(temp->right);
        TV[temp->right->data] = l+1;
    }
}
cout<<max<<min<<endl;
for(int  i =min;i<=max;i++)
{
    for(it=TV.begin();it!=TV.end();it++)
    {
        if(it->second==i)
        {
            cout<<it->first;
            break;
        }
    }
}

}

void topview_aux(node * root)

{

queue<node*> Q;

topview(root,Q);

}

答案 10 :(得分:0)

ng-change

答案 11 :(得分:0)

一种简单的递归方式:

void top_view(Node root)
{
    print_top_view(root.left, "left");
    System.out.print(root.data  + " ");
    print_top_view(root.right, "right");
}

void print_top_view(Node root, String side) {
    if(side.equals("left")) {
        if(root.left != null) {
            print_top_view(root.left, "left"); 
        }
       System.out.print(root.data + " ");
    } else if(side.equals("right")) {
        System.out.print(root.data + " ");
        if(root.right != null) {
          print_top_view(root.right, "right");  
        } 
    }
}

答案 12 :(得分:0)

void top_view(Node root)
 {
    Node left = root;
    Node right = root;
    print_left(root.left);
    System.out.print(root.data + " ");
    print_right(root.right) ;
 }

void print_left(Node start)
 {
    if(start != null)
     {
       print_left(start.left);
       System.out.print(start.data + " "); 
     } 
 }

void print_right(Node start)
 {
    if(start != null)
    {
       System.out.print(start.data + " ");    
       print_right(start.right);
    }     
  } 

答案 13 :(得分:0)

在java recursivish解决方案中。从c ++代码转换而来

void top_view(Node root)
{
    left_array(root);
    right_array(root.right);
}

void left_array(Node p)
{
    if(p==null)
        return;
    else
    {
        left_array(p.left);
        System.out.printf("%d ",p.data);
    }
}
void right_array(Node p)
{
    if(p==null)
        return;
    else
    {
        System.out.printf("%d ",p.data);
        right_array(p.right);
    }
}

答案 14 :(得分:0)

  

一个非常简单的递归解决方案,负责处理子节点的长分支。这是使用水平距离概念解决的。

public void printTopView(BNode root) {
        Map<Integer, Integer> data = new TreeMap<Integer, Integer>();
        printTopViewRecursive(data, root, 0);
        for(int key : data.keySet()) {
            System.out.print(data.get(key) +" ");
        }
    }


    private void printTopViewRecursive(Map<Integer, Integer> hDMap, BNode root, int hD) {
        if(root == null)
            return;
        if(!hDMap.containsKey(hD)) {
            hDMap.put(hD, root.data);
        }
        printTopViewRecursive(hDMap, root.left,hD - 1);
        printTopViewRecursive(hDMap, root.right, hD + 1);
    }

答案 15 :(得分:0)

C ++中更简单的方法

`// printing top view of the tree
void left_array(node *p)
{
    if(p==NULL)
    return;
    else
    {
        left_array(p->left);
        cout<<p->data<<" ";
    }
}
void right_array(node *p)
{
    if(p==NULL)
    return;
    else
    {
        cout<<p->data<<" ";
        right_array(p->right);
    }

}
void top_view(node * root)
{   int i=0;
node *t1=root;
node *t2=root;
    left_array(t2);
    right_array(t1->right);

}`

答案 16 :(得分:0)

void top_view(Node root)    
{    
    if(root.left!=null) top_view(root.left);   

    if(root.left!=null || root.right!=null)
         System.out.print(root.data + " ");

    if(root.right!=null) top_view(root.right);        
}