【力扣】重新安排行程(很难的回溯题)(未完待续)
题目描述
分析
各种意义上都很难 的一道回溯题,首先按照回溯模版写就不是很简单,因为path需要在开头的地方加上JFK,另外,判断字典序优先度如果没有写过的话也很难一下子写出来。就算把这些写出来后,在规模比较大的判例上还是会超时或者超内存。
另外,超时或者超内存不一定是代码性能的问题,也可能是几张票形成了死循环。(但是我的代码里用了used数组,所以应该不会有这个问题)
先贴一下按照模版写出的代码:
using namespace std;
vector<vector<string> > res;
vector<string> path;
vector<string> Prior(vector<vector<string> >& res){
//找到最优先的结果
//cout<<res.size()<<endl;
vector<string> best = res[0];
for(int i = 1; i < res.size(); i++){
for(int j = 0; j < best.size(); j++){
if(best[j] != res[i][j] ){
//cout<<i<<" "<<j<<" "<<best[j].compare(res[i][j])<<endl;
if(best[j].compare(res[i][j]) > 0){
best = res[i];
}
break;
}
}
}
return best;
}
void backtrace(vector<vector<string> >& tickets, vector<int>& used){
//cout<<"sizeofpath:"<<path.size()<<" sizeoftickets+1:"<<tickets.size() + 1<<endl;
if(path.size() == tickets.size()+1){
res.push_back(path);
return ;
}
for(int i = 0; i < tickets.size(); i++){
if(used[i] == 1){
continue;
}
if(tickets[i][0] == path.back()){
path.push_back(tickets[i][1]);
//cout<<tickets[i][1]<<endl;
used[i] = 1;
backtrace(tickets, used);
used[i] = 0;
path.pop_back();
}
}
}
vector<string> findItinerary(vector<vector<string> >& tickets) {
vector<int> used(tickets.size(), 0);
res.clear();
path.push_back("JFK");
backtrace(tickets, used);
//cout<<res[0][0]<<endl;
return Prior(res);
}
int main(){
string s1 = "JFK";
string s2 = "SFO";
//cout<<s1.compare(s2);
int n;
cin>>n;
vector<vector<string> > tickets ;//= {{"MUC","LHR"}, {"JFK","MUC"},{"SFO","SJC"},{"LHR","SFO"}};
vector<string> tmp;
string s;
for(int i = 0; i < n; i++){
tmp.clear();
for(int j = 0; j < 2; j++){
cin>>s;
tmp.push_back(s);
}
tickets.push_back(tmp);
}
// for(int i = 0; i < n; i++){
// for(int j = 0; j < 2;j++){
// cout<<tickets[i][j]<<" ";
// }
// cout<<endl;
// }
vector<string> result = findItinerary(tickets);
for(int i = 0; i < res.size(); i++){
for(int j = 0; j < res[0].size(); j++){
cout<<res[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
for(int i = 0; i < result.size(); i++){
cout<<result[i]<<" ";
}
return 0;
}
下面是代码随想录的代码:
class Solution {
private:
// unordered_map<出发机场, map<到达机场, 航班次数>> targets
unordered_map<string, map<string, int>> targets;
bool backtracking(int ticketNum, vector<string>& result) {
if (result.size() == ticketNum + 1) {
return true;
}
for (pair<const string, int>& target : targets[result[result.size() - 1]]) {
if (target.second > 0 ) { // 记录到达机场是否飞过了
result.push_back(target.first);
target.second--;
if (backtracking(ticketNum, result)) return true;
result.pop_back();
target.second++;
}
}
return false;
}
public:
vector<string> findItinerary(vector<vector<string>>& tickets) {
targets.clear();
vector<string> result;
for (const vector<string>& vec : tickets) {
targets[vec[0]][vec[1]]++; // 记录映射关系
}
result.push_back("JFK"); // 起始机场
backtracking(tickets.size(), result);
return result;
}
};
分析代码:
这个代码里用到了unordered_map这种数据结构,因为数据之间明显存在着映射关系,即每一票一定都对应着另一张票的终点,和某张票的起点。
涉及到了哈希表,复试应该不会考到。