<p>You are given a <strong>0-indexed</strong> 2D integer array <code>pairs</code> where <code>pairs[i] = [start<sub>i</sub>, end<sub>i</sub>]</code>. An arrangement of <code>pairs</code> is <strong>valid</strong> if for every index <code>i</code> where <code>1 &lt;= i &lt; pairs.length</code>, we have <code>end<sub>i-1</sub> == start<sub>i</sub></code>.</p>

<p>Return <em><strong>any</strong> valid arrangement of </em><code>pairs</code>.</p>

<p><strong>Note:</strong> The inputs will be generated such that there exists a valid arrangement of <code>pairs</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> pairs = [[5,1],[4,5],[11,9],[9,4]]
<strong>Output:</strong> [[11,9],[9,4],[4,5],[5,1]]
<strong>Explanation:
</strong>This is a valid arrangement since end<sub>i-1</sub> always equals start<sub>i</sub>.
end<sub>0</sub> = 9 == 9 = start<sub>1</sub> 
end<sub>1</sub> = 4 == 4 = start<sub>2</sub>
end<sub>2</sub> = 5 == 5 = start<sub>3</sub>
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> pairs = [[1,3],[3,2],[2,1]]
<strong>Output:</strong> [[1,3],[3,2],[2,1]]
<strong>Explanation:</strong>
This is a valid arrangement since end<sub>i-1</sub> always equals start<sub>i</sub>.
end<sub>0</sub> = 3 == 3 = start<sub>1</sub>
end<sub>1</sub> = 2 == 2 = start<sub>2</sub>
The arrangements [[2,1],[1,3],[3,2]] and [[3,2],[2,1],[1,3]] are also valid.
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> pairs = [[1,2],[1,3],[2,1]]
<strong>Output:</strong> [[1,2],[2,1],[1,3]]
<strong>Explanation:</strong>
This is a valid arrangement since end<sub>i-1</sub> always equals start<sub>i</sub>.
end<sub>0</sub> = 2 == 2 = start<sub>1</sub>
end<sub>1</sub> = 1 == 1 = start<sub>2</sub>
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= pairs.length &lt;= 10<sup>5</sup></code></li>
	<li><code>pairs[i].length == 2</code></li>
	<li><code>0 &lt;= start<sub>i</sub>, end<sub>i</sub> &lt;= 10<sup>9</sup></code></li>
	<li><code>start<sub>i</sub> != end<sub>i</sub></code></li>
	<li>No two pairs are exactly the same.</li>
	<li>There <strong>exists</strong> a valid arrangement of <code>pairs</code>.</li>
</ul>

# Data Structure: Hash Map (to track connections), Eulerian Path (to find the valid arrangement)
# Algorithm: Eulerian Path Algorithm for a directed graph

# Short Intuition:
# This is essentially an Eulerian path problem where we need to arrange the pairs such that there is a continuous path where the end of one pair matches the start of the next.
# The input guarantees the existence of a valid path, so we just need to find and return one such path.

# Detailed Intuition:
# - Each pair [start, end] can be thought of as a directed edge from start to end.
# - The goal is to find a sequence of these edges (pairs) where for each edge, the previous one's end matches the current one's start.
# - We can model this as a graph traversal problem where we arrange the edges in a way that forms a valid Eulerian path.
# - Using a hash map to store the edges, we find an Eulerian path starting from any vertex with an outdegree greater than 0.

# Pseudo Code:
# 1. Build a graph using a dictionary, where each key is a start point and the value is a list of endpoints.
# 2. Use a modified Eulerian path algorithm to arrange the pairs.
# 3. Return the valid arrangement.

from collections import defaultdict, deque

class Solution:
    def validArrangement(self, pairs: List[List[int]]) -> List[List[int]]:
        # Step 1: Build the graph
        graph = defaultdict(deque)
        in_degree = defaultdict(int)
        out_degree = defaultdict(int)
        
        # Step 2: Fill the graph and calculate in-degrees and out-degrees
        for u, v in pairs:
            graph[u].append(v)
            out_degree[u] += 1
            in_degree[v] += 1
        
        # Step 3: Find the starting point (where out-degree > in-degree)
        start = pairs[0][0]
        for node in out_degree:
            if out_degree[node] > in_degree[node]:
                start = node
                break
        
        # Step 4: Perform Hierholzer’s algorithm to find the Eulerian path
        result = []
        def dfs(node):
            while graph[node]:
                next_node = graph[node].popleft()
                dfs(next_node)
                result.append([node, next_node])
        
        # Start DFS from the start node
        dfs(start)
        
        # Step 5: Return the result in reverse order (since we backtrack in DFS)
        return result[::-1]

# Time Complexity: O(n), where n is the number of pairs.
# Explanation: We visit each node and edge exactly once while building the graph and during DFS traversal.

# Space Complexity: O(n)
# Explanation: Space is used for storing the graph, in-degrees, out-degrees, and the result list.

2062