重新安排行程
Leetcode 332
學習記錄自代碼隨想錄
給你一份航線列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飛機出發和降落的機場地點。請你對該行程進行重新規劃排序。
所有這些機票都屬于一個從 JFK(肯尼迪國際機場)出發的先生,所以該行程必須從 JFK 開始。如果存在多種有效的行程,請你按字典排序返回最小的行程組合。
例如,行程 [“JFK”, “LGA”] 與 [“JFK”, “LGB”] 相比就更小,排序更靠前。
假定所有機票至少存在一種合理的行程。且所有的機票 必須都用一次 且 只能用一次。
輸入:tickets = [[“MUC”,“LHR”],[“JFK”,“MUC”],[“SFO”,“SJC”],[“LHR”,“SFO”]]
輸出:[“JFK”,“MUC”,“LHR”,“SFO”,“SJC”]
輸入:tickets = [[“JFK”,“SFO”],[“JFK”,“ATL”],[“SFO”,“ATL”],[“ATL”,“JFK”],[“ATL”,“SFO”]]
輸出:[“JFK”,“ATL”,“JFK”,“SFO”,“ATL”,“SFO”]
解釋:另一種有效的行程是 [“JFK”,“SFO”,“ATL”,“JFK”,“ATL”,“SFO”] ,但是它字典排序更大更靠后。
要點:1.回溯模板上修改一些判斷條件;
2.需要開始對車票排序,之后排過序后只要找到一個方案就是所需的字母排序最小的方案;
3.檢查重復的車票,有的車票會重復;
4.檢查使用過的車票以及車票開頭是否等于上次末尾;
方法一:
class Solution {
private:// vector<string> path = {"JFK"};string start = "JFK";vector<vector<string>> result;void backtracking(vector<vector<string>>& tickets, vector<int> used, vector<string> path){if(path.size() == tickets.size() + 1){result.push_back(path);return;}// start = path.back();for(int i = 0; i < tickets.size(); i++){// 已經對車票開始排過序了,所以只要找到一個方案就是所需的字母排序最小的方案if(result.size() > 0) break;// 檢查重復的車票,有的車票會重復if (i > 0 && !used[i - 1] && tickets[i][0] == tickets[i - 1][0] && tickets[i][1] == tickets[i - 1][1]) {continue;}// 檢查使用過的車票以及車票開頭是否等于上次末尾if(used[i] == 1 || tickets[i][0] != start){continue;}start = tickets[i][1];used[i] = 1;path.push_back(tickets[i][1]);backtracking(tickets, used, path);path.pop_back();start = path.back();used[i] = 0;}}
public:vector<string> findItinerary(vector<vector<string>>& tickets){// path.clear();sort(tickets.begin(), tickets.end());vector<string> path = {"JFK"};vector<int> used(tickets.size(), 0);backtracking(tickets, used, path);// sort(result.begin(), result.end());return result[0];}
};
方法二:使用map存儲機票路徑
//使用map存儲
class Solution{
private:// 出發機場,<到達機場,標記機場是否使用過>unordered_map<string, map<string, int>> targets;// 注意此處result需要引用,不然輸入的result只是為形參,不改變原來的resultbool backtracking(vector<string>& result, vector<vector<string>>& tickets){if(result.size() == tickets.size() + 1){return true;}// target需要引用以對應更改targets, const防止更改// for(auto& target : targets[result.back()]){for(pair<const string, int>& target : targets[result.back()]){if(target.second > 0){result.push_back(target.first);target.second--;if(backtracking(result, tickets)) return true; // 這樣一找到結果就能返回result.pop_back(); // 回溯target.second++; // 回溯}}return false;}public:vector<string> findItinerary(vector<vector<string>>& tickets){targets.clear();// 記錄映射關系,map是有序的,存儲結果自動會排序,1代表沒去過,0代表去過for(const vector<string>& vec : tickets){targets[vec[0]][vec[1]]++;}vector<string> result;result.push_back("JFK");backtracking(result, tickets);return result;}
};