#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#include <unordered_map>
#include <set>
#include <algorithm>
#include <sstream>
#include <queue>
using namespace std;
/*
问题:
Given a list of airline tickets represented by pairs of departure and arrival airports [from, to],
reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK.
Thus, the itinerary must begin with JFK.
Note:
If there are multiple valid itineraries, you should return the itinerary that has the smallest
lexical order when read as a single string. For example, the itinerary ["JFK", "LGA"] has a smaller lexical order than ["JFK", "LGB"].
All airports are represented by three capital letters (IATA code).
You may assume all tickets form at least one valid itinerary.
Example 1:
tickets = [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]]
Return ["JFK", "MUC", "LHR", "SFO", "SJC"].
Example 2:
tickets = [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
Return ["JFK","ATL","JFK","SFO","ATL","SFO"].
Another possible reconstruction is ["JFK","SFO","ATL","JFK","ATL","SFO"]. But it is larger in lexical order.
分析:题目给定了多个[from,to]的二元组,现在希望能够重新构建原来的航线,
起点都是"JFK",并且希望构建的航线在字典序上是最小的
本质上就是当前的二元组中的to是下一个而元组的from。
然后不断查找。查找可以用哈希建立映射
<from ,to>,但是一个from可能对应多个to,因此建立的映射是
<from , [to1 , to2, ...]>
另外一个问题是,可能存在环,from指向to之后,to可能指向from
而且应该是递归来做,否则不能处理,
递归来做后,获得每一条最终路线
每生成一段路线,需要将一个二元组删除,在对应建立的映射中删除该映射即可。
输入:
4(票数)
MUC LHR
JFK MUC
SFO SJC
LHR SFO
5
JFK SFO
JFK ATL
SFO ATL
ATL JFK
ATL SFO
3
JFK KUL
JFK NRT
NRT JFK
输出:
JFK MUC LHR SFO SJC
JFK ATL JFK SFO ATL SFO
JFK NRT JFK KUL
报错:
Input:[["JFK","KUL"],["JFK","NRT"],["NRT","JFK"]]
Output:["JFK","KUL"]
Expected:["JFK","NRT","JFK","KUL"]
也就是说优先拼出较长的路线,然后在较长的路线中选择字典序较小的
这样就需要初始的时候递归处理,
然后对于多个结果比较
报错:
Input:
[["EZE","AXA"],["TIA","ANU"],["ANU","JFK"],["JFK","ANU"],["ANU","EZE"],["TIA","ANU"],["AXA","TIA"],["TIA","JFK"],["ANU","TIA"],["JFK","TIA"]]
Output:
["JFK","ANU","EZE","AXA","TIA","ANU","JFK","TIA","JFK"]
Expected:
["JFK","ANU","EZE","AXA","TIA","ANU","JFK","TIA","ANU","TIA","JFK"]
存在重复的路线,我只算了一次。这是set本身自带的去重属性导致的,
如果不想去重,采用优先级队列或者multiset
关键:
1
参考别人的解法:http://www.cnblogs.com/zmyvszk/p/5657056.html
题目意思理解错了,是要遍历完所有的边,不允许剩余。
java中优先级队列的poll是移除队头并返回。本题需要设定
unordered_map<string , priority<string>>的数据结构
注意递归存储的结果需要逆序
2注意C++优先级队列默认大顶堆,输出最大元素,改为小顶堆用greater<int> (例如整型)
或者用仿函数自定义比较函数
priority_queue<Type , Container , Functional>
*/
struct Compare
{
bool operator()(string& a , string& b )
{
return a > b;
}
};
class Solution {
public:
void dfs(unordered_map<string , priority_queue<string , vector<string> , Compare> >& airlineMap , string& from , vector<string>& result)
{
//不断获取剩余遍历的地方,然后删除优先级队列中最小的元素,递归处理,保存结果
while( airlineMap.find(from) != airlineMap.end() && (!airlineMap[from].empty()) )
{
string to = airlineMap[from].top();
airlineMap[from].pop();
dfs(airlineMap , to , result);
}
result.push_back(from);
}
vector<string> findItinerary(vector<pair<string, string>> tickets) {
vector<string> result;
if(tickets.empty())
{
return result;
}
unordered_map<string , priority_queue<string , vector<string> ,Compare > > airlineMap;
int size = tickets.size();
//生成 起点到终点的映射
for(int i = 0 ; i < size ; i++)
{
pair<string , string> ticket = tickets.at(i);
if(airlineMap.find(ticket.first) != airlineMap.end())
{
airlineMap[ticket.first].push(ticket.second);
}
else
{
priority_queue<string , vector<string> , Compare> toPlaces;
toPlaces.push(ticket.second);
airlineMap[ticket.first] = toPlaces;
}
}
//递归处理
string sFrom("JFK");
dfs(airlineMap , sFrom , result );
//保存的结果需要逆置
reverse(result.begin() , result.end());
return result;
}
};
void print(vector<string>& result)
{
if(result.empty())
{
cout << "no result" << endl;
return;
}
int size = result.size();
for(int i = 0 ; i < size ; i++)
{
cout << result.at(i) << " " ;
}
cout << endl;
}
void process()
{
vector<pair<string , string> > tickets;
int num;
Solution solution;
vector<string> result;
while(cin >> num )
{
tickets.clear();
for(int i = 0 ; i < num ; i++)
{
pair<string , string> ticket;
cin >> ticket.first >> ticket.second;
tickets.push_back(ticket);
}
result = solution.findItinerary(tickets);
print(result);
}
}
int main(int argc , char* argv[])
{
process();
getchar();
return 0;
}
/*
class Result
{
public:
Result(){}
Result(string& result , vector<string>& results)
{
_result = result;
_results = vector<string>(results.begin() ,results.end());
}
bool operator < (const Result& result) const
{
int value = strcmp(_result.c_str() , result._result.c_str());
// value < 0 ,说明 str1 < str2
if(value < 0 )
{
return true;
}
else
{
return false;
}
}
public:
string _result;
vector<string> _results;
};
class Solution {
public:
void dfs(unordered_map<string , set<string> >& airlineMap , string& from , vector<string>& result, vector< vector<string> >& results)
{
//如果当前位置找不到下一个结束位置,返回结果
if(airlineMap.find(from) == airlineMap.end())
{
results.push_back(result);
return;
}
set<string> toPlaces= airlineMap[from];
for(set<string>::iterator it = toPlaces.begin() ; it != toPlaces.end() ; it++)
{
string to = *it;
//将当前结果加入到结果集
result.push_back(to);
//删除当前选中的<from, to>
if(1 == toPlaces.size())
{
airlineMap.erase(from);
}
else
{
airlineMap[from].erase(to);
}
dfs(airlineMap , to , result , results);
//插入回溯
result.pop_back();
//删除回溯
if(airlineMap.find(from) != airlineMap.end())
{
airlineMap[from].insert(to);
}
else
{
set<string> places;
places.insert(to);
airlineMap[from] = places;
}
}
}
vector<string> findItinerary(vector<pair<string, string>> tickets) {
vector<string> result;
if(tickets.empty())
{
return result;
}
unordered_map<string , set<string> > airlineMap;
int size = tickets.size();
//生成 起点到终点的映射
for(int i = 0 ; i < size ; i++)
{
pair<string , string> ticket = tickets.at(i);
if(airlineMap.find(ticket.first) != airlineMap.end())
{
airlineMap[ticket.first].insert(ticket.second);
}
else
{
set<string> toPlaces;
toPlaces.insert(ticket.second);
airlineMap[ticket.first] = toPlaces;
}
}
//递归处理
string sFrom("JFK");
vector< vector<string> > results;
result.push_back(sFrom);
dfs(airlineMap , sFrom , result , results);
size = results.size();
int maxLen = INT_MIN;
vector< Result > candidateResults;
for(int i = 0 ; i < size ; i++)
{
maxLen = max(maxLen , (int)results.at(i).size());
}
//如果最大长度等于结果长度,说明
for(int i = 0 ; i < size ; i++)
{
if(maxLen == results.at(i).size())
{
stringstream stream;
for(int j = 0 ; j < maxLen ; j++)
{
stream << results.at(i).at(j);
}
string temp = stream.str();
Result result(temp , results.at(i));
candidateResults.push_back(result);
}
}
//排序
sort(candidateResults.begin() , candidateResults.end());
result = candidateResults.at(0)._results;
if(result.size() > 1)
{
return result;
}
else
{
return vector<string>();
}
}
};
*/
leecode 解题总结:332. Reconstruct Itinerary
最新推荐文章于 2023-02-04 11:05:14 发布