阿里巴巴2018校招筆試題

前幾天做了阿里的2018的校招筆試題,我投的崗位是Java研發,在這裏跟大家分享下筆試題及我的解法。

1、 題目
由於當時時間比較緊,只有四十分鐘,但是題目也只有一道,可能我比較渣,所以時間很趕,沒來得及截圖,下面是我對題目的大致記憶。

大致意思是給定一組樹節點,形式爲(id, pId, cost),其中id是節點的序號,pId是父節點的序號,cost是花費,即完成這件事情所需的花費。給定的節點可以構成一棵樹或者一個森林,需要求出樹或森林中最大的花費是多少。舉例如下:
給定節點:
1, 0, 2
2, 1, 3
3, 1, 2
4, 0, 3
構成如下森林:

                (1, 0, 2)               (4, 0, 3)
               _____|_____
              |           |
         (2, 1, 3)     (3, 1, 2)

耗費最大的肯定在葉節點,id=2的節點總花費爲父節點2+本身花費3=5,以此類推,id=3的節點花費爲4id=4的節點花費爲3,所以給定這組節點花費的最大花費是5。

(我描述的可能不是很準確,大致意思吧)

2、 思路
我剛看到題目的第一個想法就是定義一個節點類Node,然後將給定節點實例化成一個一個的節點放入List中,然後找出葉子節點,最後對對葉子節點的花費進行統計。發現這種思路需要很多List遍歷,太耗費時間,於是嘗試思考其他解法。
經過幾分鐘思考,我覺得可以優化第一種思路,同樣定義一個節點類Node,然後將給定節點實例化成一個一個的節點放入Map中,Map的key取節點id,value是Node對象。Node對象中包含節點中給定的id、pId和cost,另外加入一個標誌字段isLeaf來標識這個節點是否爲葉子節點。首先將給定節點放入Map中,然後遍歷Map中所有元素,找到葉子節點,同時統計葉子節點的花費。由於通過Map找到父節點可以直接Map.get(pId),所以可以節省很多時間。
由於時間有限,沒有時間再去思考太多,於是開始動手。

3、 實現
下面是我的具體實現:
注: main方法已經被實現好,就是獲取輸入和調用resolve方法,resolve也已經被定義好了,這裏main方法是的簡化寫法。

public class AliTest {

    public static void main(String[] args) {
        // 待輸入list
        ArrayList<Integer> idList = new ArrayList<>();
        ArrayList<Integer> pIdList = new ArrayList<>();
        ArrayList<Integer> costList = new ArrayList<>();

        // 手動構造測試數據
        idList.add(1);
        idList.add(2);
        idList.add(3);
        idList.add(4);

        pIdList.add(0);
        pIdList.add(1);
        pIdList.add(1);
        pIdList.add(0);

        costList.add(2);
        costList.add(3);
        costList.add(2);
        costList.add(3);

        int get = resolve(idList, pIdList, costList);
        System.out.println(get);
    }

    public static int resolve(ArrayList<Integer> ids, ArrayList<Integer> parents, ArrayList<Integer> costs) {
        Map<Integer, Node> nodeMap = new HashMap<>();
        for(int i = 0; i < ids.size(); i++) {
            Node node = new Node();
            node.setId(ids.get(i));
            node.setParentId(parents.get(i));
            node.setCost(costs.get(i));
            node.setIsleaf(1);
            if(nodeMap.containsKey(parents.get(i))) {
                Node pNode = nodeMap.get(parents.get(i));
                pNode.setIsleaf(0);
                nodeMap.put(parents.get(i), pNode);
            }
            nodeMap.put(ids.get(i), node);
        }

        List<Integer> costList = nodeMap.values()
                .stream()
                .filter(node -> node.getIsleaf() == 1)
                .map(node -> {
                    int myCost = node.getCost();

                    int pId = node.getParentId();
                    while(pId != 0) {
                        Node pNode = nodeMap.get(pId);
                        myCost += pNode.getCost();
                        pId = pNode.getParentId();
                    }
                    return myCost;
                }).collect(Collectors.toList());

        return costList.stream().max((h1, h2) -> h1.compareTo(h2)).get();

    }

    // 樹節點
    static class Node {
        private int id; //id
        private int parentId; // 父id
        private int cost; // 花費
        private int isleaf; // 是否爲葉節點,1表示是葉節點,0表示不是葉節點

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public int getParentId() {
            return parentId;
        }

        public void setParentId(int parentId) {
            this.parentId = parentId;
        }

        public int getCost() {
            return cost;
        }

        public void setCost(int cost) {
            this.cost = cost;
        }

        public int getIsleaf() {
            return isleaf;
        }

        public void setIsleaf(int isleaf) {
            this.isleaf = isleaf;
        }
    }

}

4、 總結
當時寫完已經沒時間測試了,直接貼上去交了。晚上我回來測試了一下,居然錯了,我檢查了一下,原來將 resolve()方法中的node.setIsleaf(1); 錯寫成node.setId(1); 了,心累。
這個題目總體來說難度不是很大,主要是平時思考得比較少,最後取最大的時候max()方法不熟悉,花了好幾分鐘,總體來說就是自己能力還亟待提高。
以上思路和實現只是我個人的一點想法,如有不對之處,還望大神指教。當然如果哪位大神有更好的思路和解法,也望不吝賜教,不勝感激!

發佈了95 篇原創文章 · 獲贊 99 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章