62
62
63
63
<!-- solution:start -->
64
64
65
- ### Solution 1
65
+ ### Solution 1: Eulerian Path
66
+
67
+ The problem is essentially about finding a path that starts from a specified starting point, passes through all the edges exactly once, and has the smallest lexicographical order among all such paths, given $n$ vertices and $m$ edges. This is a classic Eulerian path problem.
68
+
69
+ Since the problem guarantees that there is at least one feasible itinerary, we can directly use the Hierholzer algorithm to output the Eulerian path starting from the starting point.
70
+
71
+ The time complexity is $O(m \times \log m)$, and the space complexity is $O(m)$. Here, $m$ is the number of edges.
66
72
67
73
<!-- tabs:start -->
68
74
@@ -71,56 +77,43 @@ tags:
71
77
``` python
72
78
class Solution :
73
79
def findItinerary (self , tickets : List[List[str ]]) -> List[str ]:
74
- graph = defaultdict(list )
75
-
76
- for src, dst in sorted (tickets, reverse = True ):
77
- graph[src].append(dst)
78
-
79
- itinerary = []
80
-
81
- def dfs (airport ):
82
- while graph[airport]:
83
- dfs(graph[airport].pop())
84
- itinerary.append(airport)
85
-
80
+ def dfs (f : str ):
81
+ while g[f]:
82
+ dfs(g[f].pop())
83
+ ans.append(f)
84
+
85
+ g = defaultdict(list )
86
+ for f, t in sorted (tickets, reverse = True ):
87
+ g[f].append(t)
88
+ ans = []
86
89
dfs(" JFK" )
87
-
88
- return itinerary[::- 1 ]
90
+ return ans[::- 1 ]
89
91
```
90
92
91
93
#### Java
92
94
93
95
``` java
94
96
class Solution {
95
- void dfs (Map<String , Queue<String > > adjLists , List<String > ans , String curr ) {
96
- Queue<String > neighbors = adjLists. get(curr);
97
- if (neighbors == null ) {
98
- ans. add(curr);
99
- return ;
100
- }
101
- while (! neighbors. isEmpty()) {
102
- String neighbor = neighbors. poll();
103
- dfs(adjLists, ans, neighbor);
104
- }
105
- ans. add(curr);
106
- return ;
107
- }
97
+ private Map<String , List<String > > g = new HashMap<> ();
98
+ private List<String > ans = new ArrayList<> ();
108
99
109
100
public List<String > findItinerary (List<List<String > > tickets ) {
110
- Map< String , Queue< String > > adjLists = new HashMap<> ( );
101
+ Collections . sort(tickets, (a, b) - > b . get( 1 ) . compareTo(a . get( 1 )) );
111
102
for (List<String > ticket : tickets) {
112
- String from = ticket. get(0 );
113
- String to = ticket. get(1 );
114
- if (! adjLists. containsKey(from)) {
115
- adjLists. put(from, new PriorityQueue<> ());
116
- }
117
- adjLists. get(from). add(to);
103
+ g. computeIfAbsent(ticket. get(0 ), k - > new ArrayList<> ()). add(ticket. get(1 ));
118
104
}
119
- List<String > ans = new ArrayList<> ();
120
- dfs(adjLists, ans, " JFK" );
105
+ dfs(" JFK" );
121
106
Collections . reverse(ans);
122
107
return ans;
123
108
}
109
+
110
+ private void dfs (String f ) {
111
+ while (g. containsKey(f) && ! g. get(f). isEmpty()) {
112
+ String t = g. get(f). remove(g. get(f). size() - 1 );
113
+ dfs(t);
114
+ }
115
+ ans. add(f);
116
+ }
124
117
}
125
118
```
126
119
@@ -130,36 +123,77 @@ class Solution {
130
123
class Solution {
131
124
public:
132
125
vector<string > findItinerary(vector<vector<string >>& tickets) {
133
- unordered_map<string, priority_queue<string, vector<string >, greater<string >>> g;
134
- vector<string > ret;
135
-
136
- // Initialize the graph
137
- for (const auto& t : tickets) {
138
- g[t[0]].push(t[1]);
126
+ sort(tickets.rbegin(), tickets.rend());
127
+ unordered_map<string, vector<string >> g;
128
+ for (const auto& ticket : tickets) {
129
+ g[ ticket[ 0]] .push_back(ticket[ 1] );
139
130
}
131
+ vector<string > ans;
132
+ auto dfs = [ &] (auto&& dfs, string& f) -> void {
133
+ while (!g[ f] .empty()) {
134
+ string t = g[ f] .back();
135
+ g[ f] .pop_back();
136
+ dfs(dfs, t);
137
+ }
138
+ ans.emplace_back(f);
139
+ };
140
+ string f = "JFK";
141
+ dfs(dfs, f);
142
+ reverse(ans.begin(), ans.end());
143
+ return ans;
144
+ }
145
+ };
146
+ ```
140
147
141
- findItineraryInner (g, ret, "JFK");
148
+ #### Go
149
+
150
+ ```go
151
+ func findItinerary(tickets [][]string) (ans []string) {
152
+ sort.Slice(tickets, func(i, j int) bool {
153
+ return tickets[i][0] > tickets[j][0] || (tickets[i][0] == tickets[j][0] && tickets[i][1] > tickets[j][1])
154
+ })
155
+ g := make(map[string][]string)
156
+ for _, ticket := range tickets {
157
+ g[ticket[0]] = append(g[ticket[0]], ticket[1])
158
+ }
159
+ var dfs func(f string)
160
+ dfs = func(f string) {
161
+ for len(g[f]) > 0 {
162
+ t := g[f][len(g[f])-1]
163
+ g[f] = g[f][:len(g[f])-1]
164
+ dfs(t)
165
+ }
166
+ ans = append(ans, f)
167
+ }
168
+ dfs("JFK")
169
+ for i := 0; i < len(ans)/2; i++ {
170
+ ans[i], ans[len(ans)-1-i] = ans[len(ans)-1-i], ans[i]
171
+ }
172
+ return
173
+ }
174
+ ```
142
175
143
- ret = {ret.rbegin(), ret.rend()};
176
+ #### TypeScript
144
177
145
- return ret;
178
+ ``` ts
179
+ function findItinerary(tickets : string [][]): string [] {
180
+ const g: Record <string , string []> = {};
181
+ tickets .sort ((a , b ) => b [1 ].localeCompare (a [1 ]));
182
+ for (const [f, t] of tickets ) {
183
+ g [f ] = g [f ] || [];
184
+ g [f ].push (t );
146
185
}
147
-
148
- void findItineraryInner(unordered_map<string, priority_queue<string, vector<string>, greater<string>>>& g, vector<string>& ret, string cur) {
149
- if (g.count(cur) == 0) {
150
- // This is the end point
151
- ret.push_back(cur);
152
- return;
153
- } else {
154
- while (!g[cur].empty()) {
155
- auto front = g[cur].top();
156
- g[cur].pop();
157
- findItineraryInner(g, ret, front);
158
- }
159
- ret.push_back(cur);
186
+ const ans: string [] = [];
187
+ const dfs = (f : string ) => {
188
+ while (g [f ] && g [f ].length ) {
189
+ const t = g [f ].pop ()! ;
190
+ dfs (t );
160
191
}
161
- }
162
- };
192
+ ans .push (f );
193
+ };
194
+ dfs (' JFK' );
195
+ return ans .reverse ();
196
+ }
163
197
```
164
198
165
199
<!-- tabs: end -->
0 commit comments