paypal 数字对生成树

 

 

一道特别考验语言功底的题目,首先它的输入与输出,对于我这种没有处理过复杂的输入,以及输出的渣渣来说,浪费了大量的时间,好在现在还稍微来得及,不怕不怕啦。紧接着,整个题目的要求也是比较复杂的,首先允许存在重复的数字对,也就是说,在输入的过程中,需要去重。若重复,则忽略。(具体实现过程中,使用一个edges的map表来去重的。)其次,顺序不唯一,同样的输入,打乱顺序后,会导致不同的输出。比如样例1与样例3。

结合题意,且对于树这种结构,首先需要确定根节点(那个没有父节点的),其次从根节点开始能够保证遍历所有的节点,且仅仅遍历一次。这就是这道题目解题的思路。而且,看题目中的要求,数字大小为1~2^31,所以这里不能够使用数组了,所以可以使用map来存储,首先需要一个邻接表的存储方式来存储读入的数据,其次需要一个字段来判断节点是否有父节点,为了便于实现对应不同的输入顺序有不同的输出过程,需要增加一个时间戳标记位timestamp和深度标记位dist来表示距离根节点的距离。

紧接着就是bfs的过程了,bfs过程必然用到队列的,所以整个过程代码实现如下:

import java.util.*;
import java.io.*;
public class Main{
    /** 以邻接表的形式存储整个树。 */
    static HashMap<Integer,ArrayList<Integer>> hh =new HashMap<>();
    /** 存下每个点的时间戳,用于确认bfs遍历的顺序 */
    static HashMap<Integer,Integer>timestamp=new HashMap<>();
    /** 节点到根节点的距离。 */
    static HashMap<Integer,Integer>dist=new HashMap<>();
    static HashMap<Integer,Boolean>has_father=new HashMap<>();
    static HashMap<Edges,Boolean>edges=new HashMap<>();
    public static void main(String[] args) throws IOException {
        Scanner sc=new Scanner(System.in);
        BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        int n=sc.nextInt();
        while (n!=0){
            n--;
            String str[]=sc.next().split(",");
            int a=Integer.parseInt(str[0]);
            int b=Integer.parseInt(str[1]);
            /* 存储时间戳记录的次序 */
            int tm=0;
            Edges edge=new Edges(a,b);
            if (edges.containsKey(edge)){
                continue;//用来除去序列中重复的边。
            }else{
                edges.put(edge,true);
            }
            if (!timestamp.containsKey(a)){
                timestamp.put(a,tm++);
            }
            if (!timestamp.containsKey(b)){
                timestamp.put(b,tm++);
            }
            has_father.put(b,true);
            if (!hh.containsKey(a)){
                ArrayList<Integer>list=new ArrayList<>();
                list.add(b);
                hh.put(a,list);
            }else{
                hh.get(a).add(b);
            }
        }
        String result=process(n);
        System.out.println(result);
    }

    private static String process(int n) {
        String result="";
        int root=-1;
        for (Integer p: hh.keySet()){
            if (has_father.get(p)==null){
                root=p;
                break;
            }
        }
        if (root==-1){
            return "Not a tree";
        }
        else{
             ArrayList<Integer>res=bfs(root);
             /* 进行宽度优先遍历 */
            if (res.size()<timestamp.size()){
                /* 如果整个树是不连通的,则判定不是一棵树 */
                return "Not a tree";
            }else{
                result+=res.get(0)+"";
                for (int i=1;i<res.size();i++){
                    result+=","+res.get(i);
                }
            }
        }
        return result;
    }

    private static ArrayList<Integer> bfs(int root) {
        Queue<Integer>q=new LinkedList<>();
        q.offer(root);
        ArrayList<Integer>nodes = new ArrayList<>();
        dist.put(root,0);
        while(!q.isEmpty()){
            int t=q.poll();
            nodes.add(t);
            ArrayList<Integer>tem=hh.get(t);
             if (tem==null){
                continue;
            }
            for (Integer temp: tem){
                /* 当前节点已经被遍历过,说明在序列中该节点存在多个父节点 */
                if (dist.containsKey(temp)){
                    return new ArrayList<>();
                }
                dist.put(temp,dist.get(t)+1);
                q.offer(temp);
            }
        }
        /*双关键字排序*/
        ArrayList<ArrayList<Integer>>ans=new ArrayList<>();
        for (Integer ver:nodes){
            ArrayList<Integer>list=new ArrayList<Integer>();
            list.add(dist.get(ver));
            list.add(timestamp.get(ver));
            list.add(ver);
            ans.add(list);
        }
        nodes.clear();
        Collections.sort(ans, new Comparator<ArrayList<Integer>>() {
            @Override
            public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) {
                if (Objects.equals(o1.get(0), o2.get(0))){
                    return o1.get(1)-o2.get(1);
                }
                return o1.get(0)-o2.get(0);
            }
        });
        for (ArrayList<Integer>t:ans){
            nodes.add(t.get(2));
        }
        return nodes;
    }

}
class Edges{
    int first;
    int second;
    public Edges(int first,int second){
        this.first=first;
        this.second=second;
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值