1

I am trying to find a path from the root node to a given point but ends up in getting an empty array.In the output I should get List of string of path id's from root to the given point. Please check below link for detailed description about problem.

Problem Statement

I have tried below code to get string id's.

public static List<String> findPathToNode(Node rootNode, Point toFind) {
    // @ToDo Implement this routine
    List<String> nodeList = new ArrayList<>();

    return getAllNodesForPoint(rootNode, toFind, nodeList);   }

  //Recursive function to loop through all nodes of tree and return empty LinkedList   // if point not found or NOT Empty with the path to the point, if point is found

  static List<String> getAllNodesForPoint(Node n, Point p, List<String> list) {
    list.add(n.getId());
    for (Node temp : n.getChildren()) {
      if (temp.getChildren().size() > 0) {
        if (isContained(temp, p)) {
          list.add(temp.getId());
          return list;
        } else {
          getAllNodesForPoint(temp, p, list);
        }
      } else {
        list = new LinkedList<>();
        list.add(n.getId());
      }
    }
    list = new ArrayList<>();
    return list;   }

  static boolean isContained(Node e, Point p){
    Point topLeft = new Point(e.getLeft(), e.getTop());
    Point topRight = new Point(e.getLeft()+e.getWidth(), e.getTop());
    Point bottomLeft = new Point(e.getLeft(), e.getTop()+e.getHeight());
    Point bottomRight = new Point(e.getLeft()+e.getWidth(), e.getTop()+e.getHeight());
    if(topLeft.getX()<p.getX()
            &&p.getX()<topRight.getX()
            &&topLeft.getY()<p.getY()
            &&bottomLeft.getY()>p.getY()){
      return true;
    }
    else{
      return false;
    }   }

Thank you in advanced!!!

Anamika
  • 11
  • 4

2 Answers2

1

There is error in your this part of code fragment

for (Node temp : n.getChildren()) {
      if (temp.getChildren().size() > 0) {
        if (isContained(temp, p)) {
          list.add(temp.getId());
          return list;
        } else {
          getAllNodesForPoint(temp, p, list);
        }
      } else {
        list = new LinkedList<>();
        list.add(n.getId());
      }
    }
    list = new ArrayList<>();
    return list;  

We can use example given in your problem statement to explain the same.

Example :

{"id": "root" ,
"left": 0 , 
"top": 0 ,
"width": 33 , 
"height": 23 ,
"children": [{
               "id": "child-0" ,
                "left": 5 , 
                 “top": 5 ,
                 "width": 20 ,
                 "height": 10 ,
                  "children": []},
               {"id": "child-1" ,
                "left": 10 ,
                "top": 10 ,
                 "width": 20 ,
                  "height": 10 ,
                  "children": []
                }
      ]}

It starts with root node and in its children array there are two childs child-0 and child-1 . Because of this it will go in this part of code

for (Node temp : n.getChildren())

Now this for loop will run 2 times , since there are two children of root node.

But each child children array is empty so it will fail to go in this fragement of code:

if (temp.getChildren().size() > 0)

instead, it will go in the else part. But first issue is over here. Here, you are initializing an array list every time and adding this children Id. So, when the loop runs the first time for child-1 it will create a new list by this

list = new LinkedList<>();

and add child-1 to it. and next time it will again run for child-2 and reinitialize the list and add child-2 to it.

So, at the end of for loop in our list we will have only 1 entry of child-2.

But you are getting empty list as result because after ending for loop you have again reinitialized the list and you are returning empty list.This is the second issue.

list = new ArrayList<>();
return list;

The corrected code of getAllNodesForPoint is

list.add(n.getId());
    for (Node temp : n.getChildren()) {
      if (temp.getChildren().size() > 0) {
        if (isContained(temp, p)) {
          list.add(temp.getId());
          return list;
        } else {
          getAllNodesForPoint(temp, p, list);
        }
      } else {
        list.add(temp.getId());
      }
    }
    return list;   }
  • @Prerana Gupta Now its adding root node 3 times in an array – Anamika Feb 16 '20 at 05:19
  • In the else part of `for` loop where you are doing `list.add(n.getId())` you need to do` list.add(temp.getId())` since `n` refers to starting Node and you are looping through child nodes which are referenced by Node` temp` . Have edited my corrected code of `getAllNodesForPoint` as well. –  Feb 16 '20 at 05:38
  • Now its adding all the points in the array root, child0 and child 1 for all points – Anamika Feb 16 '20 at 06:28
  • You are trying for above example or some other ? –  Feb 16 '20 at 06:39
  • I am trying different example but the concept is same – Anamika Feb 16 '20 at 13:52
1

Below is the code snippet that would do the job as stated in the Problem statement:

private static void getPath(Node root, Point p, List<String> result) {
    if (root != null) {
        result.add(root.getId());
        List<Node> childNodes = root.getChildren();
        if (childNodes != null && !childNodes.isEmpty()) {
            Node child = null;
            for (Node node : childNodes) {
                if (isLeftBoundCondtionMet(node, p) && isTopBoundCondtionMet(node, p)) {
                    child = node;
                }
            }
            getPath(child, p, result);
        }
    }
}

public static Boolean isLeftBoundCondtionMet(Node root, Point p) {
    return root.getLeft() < p.getX() && (p.getX() < (root.getLeft() + root.getWidth()));
}

public static Boolean isTopBoundCondtionMet(Node root, Point p) {
    return root.getTop() < p.getY() && (p.getY() < (root.getTop() + root.getHeight()));
}
  • Baiser It is working for all the files except this [link](https://docdro.id/KNwEZun) for one point [x=32,y=3]. Its showing path node/node-1/node-1-6, But it has to be node/node-1/node-1-6/node-1-6-8/node-1-6-8-4. – Anamika Feb 16 '20 at 13:34
  • Can you elaborate more on which input set you are referring to? The Id's mentioned in the link is different compared to the result you have specified above. – Arjun Baiswar Feb 16 '20 at 19:49
  • Previous ID's were just a small sample to understand the problem. As the problem is the same it should work on all id's of hierarchy. To be precise, it is not working on node id's of [link](https://www.docdroid.net/KNwEZun/input.txt) for the [points](https://docdro.id/GEvHkJR) – Anamika Feb 18 '20 at 11:08