LeetCode332 - Reconstruct Itinerary(重新安排行程 图转树 后序遍历)

LeetCode332 - Reconstruct Itinerary(重新安排行程 图转树 后序遍历)

题目链接
题目

在这里插入图片描述

解析
  • 由于必须要按照字典序最小的来访问某个结点的孩子,所以在查找节点的孩子的map中使用一个优先队列存放,每次取出来的是字典序最小的;

  • 然后按照类似后序遍历的顺序遍历这个图(先访问自己孩子,然后访问自己),然后在反转过来,这样可以得到正确的答案;

  • 也可以理解为dfs的时候,是先访问自己的孩子,然后访问自己,最后将访问的顺序翻转过来即可,需要注意的时候一定要使用后序的方式,不然会在选择的时候出错(或者说不能正确访问所有的结点);

在这里插入图片描述

class Solution {
    
    private HashMap<String, PriorityQueue<String>> map;
    private List<String>res;
    
    public List<String> findItinerary(String[][] tickets) {
        res = new LinkedList<>();
        map = new HashMap<>();
        for (String[] s : tickets) {
            if (map.get(s[0]) == null) {
                PriorityQueue<String>pq = new PriorityQueue<>();
                pq.add(s[1]);
                map.put(s[0], pq);
            }else {
                map.get(s[0]).add(s[1]);
            }
        }
        visit("JFK");
        return res;
    }

    public void visit(String cur) {
        while(map.containsKey(cur) && !map.get(cur).isEmpty())
            visit(map.get(cur).poll()); // 访问孩子(最小的孩子)并删除这条边
        res.add(0, cur); // 在头部添加 (双向队列)
    }
}

非递归写法:

class Solution {
    
    private HashMap<String, PriorityQueue<String>> map;
    private List<String>res;
    
    public List<String> findItinerary(String[][] tickets) {
        res = new LinkedList<>();
        map = new HashMap<>();
        for (String[] s : tickets) {
            if (map.get(s[0]) == null) {
                PriorityQueue<String>pq = new PriorityQueue<>();
                pq.add(s[1]);
                map.put(s[0], pq);
            }else {
                map.get(s[0]).add(s[1]);
            }
        }
        Stack<String>stack = new Stack<>();
        stack.push("JFK");
        while(!stack.isEmpty()){
            while(map.containsKey(stack.peek()) && !map.get(stack.peek()).isEmpty())
                stack.push(map.get(stack.peek()).poll());
            res.add(0, stack.pop());
        }
        return res;
    }
}

C++:

class Solution {
public:
    vector<string> findItinerary(vector<pair<string, string>> tickets) {
        for(const auto & pair : tickets)
            map[pair.first].insert(pair.second);
        visit("JFK");
        return vector<string>(res.rbegin(), res.rend());
    }
private:
    unordered_map<string, multiset<string>>map;
    vector<string>res;
    
    void visit(string cur){
        while(map[cur].size()){
            string next = *map[cur].begin();
            map[cur].erase(map[cur].begin());
            visit(next);
        }
        res.push_back(cur);
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值