1. 程式人生 > 其它 >322.重新安排行程

322.重新安排行程

技術標籤:# leetcode

  • 322.重新安排行程

  • 思路:
    vector<vector>& tickets;tickets的元素是一對出發機場和目的機場,我們目的是找一條起點為"JFK"的路徑把它們串起來;
    運用回溯,每選一趟航班並把它新增到path中,然後從可選集合中去掉它,直到把所有航班都去掉(不去掉的話可能會死迴圈);
    終止條件:path包含了所有站點;
    迴圈:由於同一個出發機場可能對應多個到達機場,且題目要求如果最終找到不止一條合理路徑path,應選擇最小的那個。這裡為了表示一個出發機場對映多個到達機場,可以用unordered_map<出發機場, multiset>,但對multiset去掉航班的這個動作會導致迭代器失效。因此選擇unordered_map<出發機場, map<到達機場,航班次數>>,使用map保證對於同一個出發機場的航班,按從小到大排序,保證了選出來的一定是那個最合理的,省去了先找出所有合理的行程再選出最小的這個過程。同時去掉航班這個動作可以通過減少航班次數來操作,避免了迭代器失效;

    此題的回溯法返回值使用bool而不是void,因為當找到合理行程時需要提前返回,否則當出現多條合理行程時,最終得到的是一定是最大的那條;

class Solution {
private:
    int ticketNums;
    //unordered_map<出發機場, map<到達機場, 航班次數>> targets;
    unordered_map<string, map<string, int>> targets;//map是有序的,因此對於同一個出發機場的所有到達機場是按從小到大排序的,這樣在遍歷時,會從最小的開始找;

    bool
backtracking(vector<string>& path) { //找到合理的行程,傳回上一層 if (path.size() == ticketNums + 1) { //n+1個站點需要n趟航班 return true; } for (pair<const string, int>& dest : targets[path.back()]) { if (dest.second > 0) { path.
push_back(dest.first); --dest.second; if (backtracking(path)) return true; //接住下一層的true,並逐層傳上去 ++dest.second; path.pop_back(); } } return false; } public: vector<string> findItinerary(vector<vector<string>>& tickets) { ticketNums = tickets.size(); for (const vector<string>& ticket : tickets) {//創建出發機場到目的機場的對映 targets[ticket[0]][ticket[1]]++; } vector<string> path; path.reserve(ticketNums); back_inserter(path) = "JFK";//提前 backtracking(path);//題目說至少有一種合理行程,因此這裡的返回值一定為true,且是最小的; return path; } };
  • 總結:
  1. 對於一對多有兩種表示法:
unordered_map<A, map<B, int>>;
unordered_map<A, multiset<B>>;