2018秋招-阿里内推编程题

阿里巴巴的ODPS大数据处理平台可以启动一系列并发的作业,每个作业中存在一系列存在父子关系的任务。每个任务用一个三元组表示–(任务id,父任务id,执行开销),其中任务id是一个正整数(>0);父任务id为0表示根任务,每个作业存在一个唯一的根任务,并且所有的任务,如果其父任务id不为0,那么必然是一个已经存在的根任务id;执行开销是一个正整数(>0)。系统中至少存在一个作业。

举例如下:
(1, 0, 2) (2, 0, 3) (3, 1, 2) (4, 1, 3)
对应的任务关系是:
1(2) 2(3)
/ \
3(2) 4(3)
注:括号内的数字表示任务开销。


很容易看出来,这些任务树构成了一个森林。每颗任务树有若干个叶子节点,从根节点到叶子结点的路径上所有的执行开销,称作叶子节点对应任务的总开销。例如上面一共有3个叶子节点任务,分别是任务3, 4和2,对应的总开销分别是4, 5和3。总开销最大的叶子节点任务是4,对应的总开销是5。

现在需要编写程序,针对输入的任务数据,找到总开销最大的叶子节点任务对应的总开销,比如针对上面例子,输出5。

示例输入:
1 0 2
2 0 3
3 1 2
4 1 3
0

示例输出:
5

//定义树的结点
class TreeNode{
    private Integer id;
    private Integer parentId;
    private int cost;
    private Map<Integer,TreeNode> childs = new HashMap<Integer,TreeNode>();//存放所有子结点 <子结点Id,子结点>
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getParentId() {
        return parentId;
    }
    public void setParentId(Integer parentId) {
        this.parentId = parentId;
    }
    public int getCost() {
        return cost;
    }
    public void setCost(int cost) {
        this.cost = cost;
    }
    public Map<Integer, TreeNode> getChilds() {
        return childs;
    }
    public void setChilds(Map<Integer, TreeNode> childs) {
        this.childs = childs;
    }
}


public class Main{


    public static void main(String[] args) {

        ArrayList<Integer> _ids = new ArrayList<Integer>();
        ArrayList<Integer> _parents = new ArrayList<Integer>();
        ArrayList<Integer> _costs = new ArrayList<Integer>();

        Scanner in = new Scanner(System.in);
        String line = in.nextLine();

        while(line != null && !line.isEmpty()) {
            if(line.trim().equals("0")) break;
            String []values = line.trim().split(" ");
            if(values.length != 3) {
                break;
            }
            _ids.add(Integer.parseInt(values[0]));
            _parents.add(Integer.parseInt(values[1]));
            _costs.add(Integer.parseInt(values[2]));
            line = in.nextLine();
        }
        int res = resolve(_ids, _parents, _costs);

        System.out.println(String.valueOf(res));
    }

         // write your code here
    public static int resolve(ArrayList<Integer> ids, ArrayList<Integer> parents, ArrayList<Integer> costs) {
        TreeNode root = creatTree(ids, parents, costs);
        IteratorTree(root, 0);

        //获取ArrayList中最大值
        int max = pathValueList.get(0);
        for(int i = 1; i < pathValueList.size(); i++){
            if(pathValueList.get(i) > max){
                max = pathValueList.get(i);
            }
        }
        return max;
    }

  //构建一棵多叉树
    public static TreeNode creatTree(ArrayList<Integer> ids, ArrayList<Integer> parents, ArrayList<Integer> costs){
        //创建根节点
        TreeNode root = new TreeNode();
        Map<Integer, TreeNode> maps = new HashMap<Integer, TreeNode>();
        //遍历所有结点信息,将所有结点相关信息放入maps中
        for(int i = 0; i < ids.size(); i++){
            TreeNode node = new TreeNode();
            node.setId(ids.get(i));
            node.setParentId(parents.get(i));
            node.setCost(costs.get(i));
            maps.put(ids.get(i), node);
        }
        //遍历map,将父结点为0的结点放到根结点下,否则在相应父节点下添加子结点
        for(Map.Entry<Integer, TreeNode> entry : maps.entrySet()){
            TreeNode node = entry.getValue();
            Integer partentId = node.getParentId();
            if(partentId == 0){
                root.getChilds().put(node.getId(), node);//node.getId()等价于node.getKey()
            }else{
                TreeNode pNode = maps.get(partentId);
                pNode.getChilds().put(node.getId(), node);
            }
        }
        return root;
    }

    //遍历多叉树,寻找最优解
    private static List<Integer> pathValueList = new ArrayList<Integer>();
    public static void IteratorTree(TreeNode root, int sum){

        int tmp = sum;
        if(root != null){
            for(Map.Entry<Integer, TreeNode> entry : root.getChilds().entrySet()){

                sum = tmp;
                sum += entry.getValue().getCost();

                if(entry.getValue().getChilds() != null && entry.getValue().getChilds().size() > 0){
                    IteratorTree(entry.getValue(), sum);
                }else{
                    pathValueList.add(sum);//遍历完一条路径,将这条路径和记录下来
                }
            }
        }
    }

}

如有错误,欢迎指正!

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值