#1490 : Tree Restoration

微软 2017春招真题

题目

There is a tree of N nodes which are numbered from 1 to N. Unfortunately, its edges are missing so we don't know how the nodes are connected. Instead we know:

  1. Which nodes are leaves
  2. The distance (number of edges) between any pair of leaves
  3. The depth of every node (the root's depth is 1)
  4. For the nodes on the same level, their order from left to right

Can you restore the tree's edges with these information? Note if node u is on the left of node v, u's parent should not be on the right of v's parent.
tree-restoration.png
输入
The first line contains three integers N, M and K. N is the number of nodes. M is the depth of the tree. K is the number of leaves.
The second line contains M integers A1, A2, ... AM. Ai represents the number of nodes of depth i.
Then M lines follow. The ith of the M lines contains Ai numbers which are the nodes of depth i from left to right.  
The (M+3)-th line contains K numbers L1, L2, ... LK, indicating the leaves.
Then a K × K matrix D follows. Dij represents the distance between Li and Lj.1 ≤ N ≤ 100
输出
For every node from 1 to N
 output its parent. Output 0 for the root's parent.
样例输入
8 3 5
1 3 4
1
2 3 4
5 6 7 8
3 5 6 7 8
0 3 3 3 3
3 0 2 4 4
3 2 0 4 4
3 4 4 0 2
3 4 4 2 0
样例输出
0 1 1 1 2 2 4 4

分析

首先,给出的测试用例太过简单,先构建一个复杂的测试用例:
Paste_Image.png
从下往上,从左往右遍历:
第六层(最下层):
第一个节点26,其父节点一定是第五层第一个非叶子节点20。同时,在距离矩阵中增加节点20,与其他节点距离为节点26与其他节点距离-1
第二个节点27,若和26的距离为2,则其父节点也是20(×),否则,其父节点是第五层第二个非叶子节点22(√)同时,在距离矩阵中增加节点22,与其他节点距离为节点27与其他节点距离-1
第三个节点28,若和27的距离为2,则其父节点也是22(√),否则,其父节点是第五层第三个非叶子节点24(×)
......
第六层遍历结束,明确了第六层所有节点的父节点,也将第五层所有非叶子节点加入距离矩阵


第五层(倒数第二层):
第一个节点19,其父节点一定是第四层第一个非叶子节点13。同时,在距离矩阵中增加节点13,与其他节点距离为节点19与其他节点距离-1
第二个节点20,若和19的距离为2,则其父节点也是13(√),否则,其父节点是第四层第二个非叶子节点14(×)
......
第五层遍历结束,明确了第五层所有节点的父节点,也将第五层所有非叶子节点加入距离矩阵
......


(一直遍历到第三层)

第二层:
所有节点的父节点都是根节点(第一层的唯一节点)

第一层:
根节点的父节点为0

解答

解法1:结果是Wrong Answer,然而并不知道为什么,谁能帮我看看错在哪了哇~

    import java.util.Scanner;
    import java.util.Map;
    import java.util.Iterator;
    import java.util.LinkedHashMap;
    import java.util.concurrent.ConcurrentHashMap;

    public class Main_2 {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();//节点数8
            int m = sc.nextInt();//树深度3
            int k = sc.nextInt();//叶子树5
            int[] a = new int[m];//深度为i的节点数
            int[][] arr = new int[m][];//每行的节点data
            Node[][] nodes = new Node[m][];//每行的节点
            Map<Integer, Node> nodesMap = new LinkedHashMap<>();//存节点
            Map<Node, Map<Node,Integer>> distanceMap = new ConcurrentHashMap<>();//存节点间距离(叶子+非叶子)

            for (int i = 0; i < m; i++) {
                a[i] = sc.nextInt();
                arr[i] = new int[a[i]];
                nodes[i] = new Node[a[i]];
            }

            for (int i = 0; i < m; i++) {
                for (int j = 0; j < a[i]; j++){
                    arr[i][j] = sc.nextInt();
                    nodes[i][j] = new Node();
                    nodes[i][j].data = arr[i][j];
                    nodes[i][j].level = i + 1;
                    nodesMap.put(arr[i][j],nodes[i][j]);

                    if(i == 0){
                        nodes[i][j].parent = null;
                    }
                    else if(i == 1){
                        nodes[i][j].parent = nodes[0][0];
                    }
                }
            }
            int[] l = new int[n];//叶子 3 5 6 7 8
            for(int i = 0; i < k; i++){
                l[i] = sc.nextInt();
                nodesMap.get(l[i]).isLeaf = true;
            }

            int[][] d = new int[n][n];//叶子节点间距离

            for (int i = 0; i < k; i++) {
                Map<Node, Integer> tempMap = new ConcurrentHashMap<>();
                for (int j = 0; j < k; j++){
                    d[i][j] = sc.nextInt();
                    if (l[i] < l[j]){
                        tempMap.put(nodesMap.get(l[j]),d[i][j]);
                        distanceMap.put(nodesMap.get(l[i]),tempMap);
                    }
                }
            }
            //从下往上,从左往右遍历
            for(int i = m - 1; i >= 2; i--){
                int ii = i - 1;//上一层
                int jj = 0;//上一层第0个节点
                Node lastNode = null;
                for(int j = 0; j < a[i]; j++){
                    if (lastNode != null){//不是本层第一个节点,计算该节点与本层上一个节点的距离
                        int distance = (distanceMap.get(lastNode) != null && distanceMap.get(lastNode).get(nodes[i][j]) != null) ? distanceMap.get(lastNode).get(nodes[i][j]) : distanceMap.get(nodes[i][j]).get(lastNode);
                        if (distance == 2){
                            nodes[i][j].parent = lastNode.parent;
                            continue;
                        }
                    }

                    while (nodes[ii][jj].isLeaf){
                        jj++;
                    }

                    nodes[i][j].parent = nodes[ii][jj];
                    //在距离矩阵中增加其父节点
                    Iterator it1 = distanceMap.entrySet().iterator();

                    while (it1.hasNext()) {
                        Map.Entry outerEntry = (Map.Entry) it1.next();
                        Node outerKey = (Node) outerEntry.getKey();
                        Map<Node,Integer> outerValue = (Map<Node,Integer>) outerEntry.getValue();

                        if(outerKey == nodes[i][j]){
                            Map<Node, Integer> tempMap = new ConcurrentHashMap<>();
                            Iterator it2 = outerValue.entrySet().iterator();
                            while (it2.hasNext()) {
                                Map.Entry entry = (Map.Entry) it2.next();
                                Node innerKey = (Node) entry.getKey();
                                Integer innerValue = (Integer) entry.getValue();
                                tempMap.put(innerKey,innerValue - 1);
                            }
                            distanceMap.put(nodes[i][j].parent,tempMap);
                        }

                        else{
                            Iterator it2 = outerValue.entrySet().iterator();
                            while (it2.hasNext()) {
                                Map.Entry entry = (Map.Entry) it2.next();
                                Node innerKey = (Node) entry.getKey();
                                Integer innerValue = (Integer) entry.getValue();

                                if(innerKey == nodes[i][j]){
                                    Map<Node, Integer> tempMap = distanceMap.get(outerKey);
                                    tempMap.put(nodes[i][j].parent,innerValue - 1);
                                    distanceMap.put(outerKey,tempMap);
                                }
                            }
                        }

                    }
                    lastNode = nodes[i][j];
                    jj++;
                }
            }
            for (Map.Entry<Integer, Node> entry : nodesMap.entrySet()) {
                Node thisNode = entry.getValue();
                int result = (thisNode.parent != null) ? thisNode.parent.data : 0;
                System.out.print(result+" ");
            }
        }
    }
    class Node{
        public Node parent;
        public int data;
        public int level;
        public boolean isLeaf;
    }

附两个测试用例:
9 4 6
1 2 3 4
9
1 10
2 3 4
5 6 7 8
3 5 6 7 8 10
0 3 3 3 3 3
3 0 2 4 4 4
3 2 0 4 4 4
3 4 4 0 2 4
3 4 4 2 0 4
3 4 4 4 4 0


31 6 13 1 4 6 7 7 6 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 3 8 12 15 19 21 23 26 27 28 29 30 31 0 3 4 4 5 5 5 6 6 6 6 6 6 3 0 3 5 4 4 6 5 7 7 7 7 7 4 3 0 6 5 5 7 6 8 8 8 8 8 4 5 6 0 7 7 7 8 4 4 8 8 8 5 4 5 7 0 4 8 3 9 9 9 9 9 5 4 5 7 4 0 8 5 9 9 9 9 9 5 6 7 7 8 8 0 9 9 9 7 7 7 6 5 6 8 3 5 9 0 10 10 10 10 10 6 7 8 4 9 9 9 10 0 2 10 10 10 6 7 8 4 9 9 9 10 2 0 10 10 10 6 7 8 8 9 9 7 10 10 10 0 2 4 6 7 8 8 9 9 7 10 10 10 2 0 4 6 7 8 8 9 9 7 10 10 10 4 4 0
posted @ 2017-04-01 18:48  妙音天女  阅读(595)  评论(0编辑  收藏  举报