leecode 解题总结:332. Reconstruct Itinerary

#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>();
		}
    }
};
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值