Problem#
You are given a 0-indexed 2D integer array pairs
where pairs[i] = [starti, endi]
. An arrangement of pairs
is valid if for every index i
where 1 <= i < pairs.length
, we have endi-1 == starti
.
Return _any valid arrangement of _pairs
.
Note: The inputs will be generated such that there exists a valid
arrangement of pairs
.
Examples#
Example 1:
1
2
3
4
5
6
Input: pairs = [[ 5 , 1 ],[ 4 , 5 ],[ 11 , 9 ],[ 9 , 4 ]]
Output: [[ 11 , 9 ],[ 9 , 4 ],[ 4 , 5 ],[ 5 , 1 ]]
Explanation: This is a valid arrangement since endi- 1 always equals starti.
end0 = 9 == 9 = start1
end1 = 4 == 4 = start2
end2 = 5 == 5 = start3
Example 2:
1
2
3
4
5
6
7
Input: pairs = [[ 1 , 3 ],[ 3 , 2 ],[ 2 , 1 ]]
Output: [[ 1 , 3 ],[ 3 , 2 ],[ 2 , 1 ]]
Explanation:
This is a valid arrangement since endi- 1 always equals starti.
end0 = 3 == 3 = start1
end1 = 2 == 2 = start2
The arrangements [[ 2 , 1 ],[ 1 , 3 ],[ 3 , 2 ]] and [[ 3 , 2 ],[ 2 , 1 ],[ 1 , 3 ]] are also valid.
Example 3:
1
2
3
4
5
6
Input: pairs = [[ 1 , 2 ],[ 1 , 3 ],[ 2 , 1 ]]
Output: [[ 1 , 2 ],[ 2 , 1 ],[ 1 , 3 ]]
Explanation:
This is a valid arrangement since endi- 1 always equals starti.
end0 = 2 == 2 = start1
end1 = 1 == 1 = start2
Constraints:
1 <= pairs.length <= 105
pairs[i].length == 2
0 <= starti, endi <= 109
starti != endi
No two pairs are exactly the same.
There exists a valid arrangement of pairs
.
Solution#
Method 1 - Using directed graph and track degrees of node#
The problem is to find a valid arrangement of pairs such that for every index i
where 1 <= i < pairs.length
, end[i-1] == start[i]
. The approach is to:
Create a directed graph where each pair is represented as an edge from start
to end
.
Track the in-degrees and out-degrees of each node to identify the start node (a node with out-degree > in-degree
).
Utilize Depth-First Search (DFS) to traverse the graph from the start node to obtain a valid path.
Code#
Java
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class Solution {
public int [][] validArrangement (int [][] pairs) {
Map< Integer, List< Integer>> graph = new HashMap<> ();
Map< Integer, Integer> inDegree = new HashMap<> ();
Map< Integer, Integer> outDegree = new HashMap<> ();
// Build graph and degree maps
for (int [] pair : pairs) {
graph.computeIfAbsent (pair[ 0] , k -> new ArrayList<> ()).add (pair[ 1] );
outDegree.put (pair[ 0] , outDegree.getOrDefault (pair[ 0] , 0) + 1);
inDegree.put (pair[ 1] , inDegree.getOrDefault (pair[ 1] , 0) + 1);
}
// Find start node (where out-degree > in-degree)
int start = pairs[ 0][ 0] ;
for (int key : outDegree.keySet ()) {
if (outDegree.get (key) > inDegree.getOrDefault (key, 0)) {
start = key;
break ;
}
}
// Perform a DFS to find a valid arrangement (Eulerian path)
List< int []> ans = new ArrayList<> ();
Deque< Integer> stack = new ArrayDeque<> ();
stack.push (start);
while (! stack.isEmpty ()) {
int node = stack.peek ();
if (graph.containsKey (node) && ! graph.get (node).isEmpty ()) {
stack.push (graph.get (node).remove (graph.get (node).size () - 1));
} else {
stack.pop ();
if (! stack.isEmpty ()) {
ans.add (new int [] {stack.peek (), node});
}
}
}
Collections.reverse (ans);
return ans.toArray (new int [ ans.size ()][] );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution :
def validArrangement (self, pairs: List[List[int]]) -> List[List[int]]:
graph: Dict[int, List[int]] = defaultdict(list)
in_degree: Dict[int, int] = defaultdict(int)
out_degree: Dict[int, int] = defaultdict(int)
# Build graph and degree maps
for u, v in pairs:
graph[u]. append(v)
out_degree[u] += 1
in_degree[v] += 1
# Find start node (where out-degree > in-degree)
start: int = pairs[0 ][0 ]
for node in out_degree:
if out_degree[node] > in_degree[node]:
start = node
break
# Perform a DFS to find a valid arrangement (Eulerian path)
ans: List[List[int]] = []
stack: Deque[int] = deque([start])
while stack:
node: int = stack[- 1 ]
if graph[node]:
stack. append(graph[node]. pop())
else :
stack. pop()
if stack:
ans. append([stack[- 1 ], node])
ans. reverse()
return ans
Complexity#
⏰ Time complexity: O(n)
, where n
is the number of pairs. We traverse the pairs and an Eulerian path in linear time.
🧺 Space complexity: O(n)
, for storing the graph and the answer.