题目描述
给你一个下标从 0 开始的二维整数数组 pairs ,其中 pairs[i] = [starti, endi] 。如果 pairs 的一个重新排列,满足对每一个下标 i ( 1 <= i < pairs.length )都有 endi-1 == starti ,那么我们就认为这个重新排列是 pairs 的一个 合法重新排列 。
请你返回 任意一个 pairs 的合法重新排列。
注意:数据保证至少存在一个 pairs 的合法重新排列。
思路分析
- 入度为2时,从出度为1的结点开始,入度为0任选结点
- 逆向输出各结点
-
circuit保存当前走到死胡同的一组连接的结点
-
curr_path的top就是当前可以继续展开bfs搜索的当前主线的结尾结点
堆栈写法代码如下
class Solution {
public:
vector<int> printCircuit(int curr,map<int,vector<int>> adj){
// adj represents the adjacency list of
// the directed graph
// edge_count represents the number of edges
// emerging from a vertex
unordered_map<int,int> edge_count;
for (auto &i:adj)
//find the count of edges to keep track
//of unused edges
edge_count[i.first] = i.second.size(); //对应下标取边数
// Maintain a stack to keep vertices
stack<int> curr_path;
// vector to store final circuit
vector<int> circuit;
// start from any vertex
curr_path.push(curr);
int curr_v = curr; // Current vertex
while (!curr_path.empty())
{
// If there's remaining edge
if (edge_count[curr_v]){
// Push the vertex
curr_path.push(curr_v);
// Find the next vertex using an edge
int next_v = adj[curr_v].back(); //每次从最后一个元素取(考虑时间复杂度)
// and remove that edge
edge_count[curr_v]--;
adj[curr_v].pop_back();
// Move to next vertex
curr_v = next_v;
}
// back-track to find remaining circuit
else //到最后也会重复执行这一过程
{
circuit.push_back(curr_v); //保留在回路中
// Back-tracking
curr_v = curr_path.top(); //获取当前元素
curr_path.pop(); //还要退栈
}
}
reverse(circuit.begin(),circuit.end());
return circuit;
}
vector<vector<int>> validArrangement(vector<vector<int>>& pairs) {
map<int,vector<int>> adj;
map<int,pair<int,int>> mp; //统计所有点的入度和出度
int curr=pairs[0][0];
for(auto &t:pairs){
adj[t[0]].push_back(t[1]);
mp[t[0]].second++; mp[t[1]].first++;
}
for(auto &t:mp)
if((t.second.second-t.second.first)==1) curr=t.first;
vector<int> c=printCircuit(curr,adj);
vector<vector<int>> p;
for(int i=0;i<c.size()-1;i++)
p.push_back({c[i],c[i+1]});
return p;
}
};
dfs方法如下,但容易爆栈
class Solution {
public:
vector<vector<int>> validArrangement(vector<vector<int>>& pairs) {
map<int,vector<int>> adj;
map<int,pair<int,int>> mp; //统计所有点的入度和出度
int curr=pairs[0][0];
for(auto &t:pairs){
adj[t[0]].push_back(t[1]);
mp[t[0]].second++; mp[t[1]].first++;
}
for(auto &t:mp)
if((t.second.second-t.second.first)==1) curr=t.first;
vector<vector<int>> p;
function<void(int)> dfs = [&](int u) {
while (!adj[u].empty()) {
int v = adj[u].back();
adj[u].pop_back();
dfs(v);
p.push_back({u, v}); //相当于之后的
}
};
dfs(curr);
reverse(p.begin(),p.end());
return p;
}
};