Leetcode: 332.Reconstruct Itinerary
挑这道题呢,是因为看到才28%的通过率,感觉应该很精妙。结果发现我错了,其实是因为是一个巨坑/微笑。
题目是这样的,有一堆机票,让你去找出里面的一个行程,然后输出,输出的要求是:
- 多条行程的时候,输出字典序最小的那条
看起来就是一个历遍的问题,然后因为只需要输出字典序最小,所以我不如一开始就先给边排序(用set),然后遇到的第一条路输出就可以了。
所以一开始我是这样的:
Code
vector<string> result;
void dfs(unordered_map<string, set<string>> graphs,
string now,vector<string> tResult)
{
if( !graphs[now].empty())
{
auto temp = graphs[now].begin();
now = *temp;
graphs[now].erase(temp);
result.push_back(now)
dfs(graphs,now,tResult);
}
}
vector<string> findItinerary(vector<pair<string, string>> tickets)
{
unordered_map<string, set<string>> graphs;
//unordered_map<string, set<string>::iterator> visitedNeigh;
result.clear();
for(auto it : tickets)
{
graphs[it.first].insert(it.second);
//visitedNeigh[it.first] = graphs[it.first].begin();
}
vector<string> tResult;
tResult.push_back("JFK");
dfs(graphs,"JFK",tResult);
return result;
}
大概想法是用unordered_map来装图,用set来装edge(自动排序),然后每次历遍一个边后把这条边删除掉。最后找一条字典序最小的、最长的路。
然而坑就在这里了。其实这个题目还有个条件没说,就是:
- 优先情况下,找到最长的路,路等长的时候,才会输出字典序最小的一条
……看到discuss里 一堆人几个月前就问说这个条件为什么不给了……
这样难度就大了些。因为你需要给每一条边一个visited值,而且每次都是对目标点的所有边进行dfs,而且dfs完了之后,还有把visited位复位……
大概是长这样的:
代码
class Solution {
public:
unordered_map<string,multimap<string,bool> > Edges;
bool Visit(const string &AP,int TV, int TT, vector<string> &Res)
{
Res.push_back(AP);
if(TT == TV)
{
return true;
}
for(auto &P : Edges[AP])
{
if(P.second == false)
{
P.second = true;
TV++;
if(Visit(P.first,TV,TT,Res))
{
return (true);
}
P.second = false;
TV--;
}
}
Res.pop_back();
return (false);
}
vector<string> findItinerary(vector<pair<string, string>> tickets)
{
int TotalVisited = 1;
int TotalTickets = 1;
for(auto &p : tickets)
{
Edges[p.first].insert(make_pair(p.second,false));
TotalTickets++;
}
vector<string> Res;
if(
Visit("JFK",TotalVisited,TotalTickets,Res) == false)
{
Res.clear();
}
return (Res);
}
};
嗯,是的,题目的机票都是可以刚好组成一次旅行的,不会有冗余,不然dfs深度会很深,可能会爆掉……题目就更加难了……
这个故事告诉我们,做leetcode前,看看discuss里面是不是最近一年都没什么人动过这个题……要相信大众的眼光……