Skip to content

feat: add solutions to lc problem: No.0332 #3278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 95 additions & 61 deletions solution/0300-0399/0332.Reconstruct Itinerary/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,13 @@ tags:

<!-- solution:start -->

### 方法一
### 方法一:欧拉路径

题目实际上是给定 $n$ 个点和 $m$ 条边,要求从指定的起点出发,经过所有的边恰好一次,使得路径字典序最小。这是一个典型的欧拉路径问题。

由于本题保证了至少存在一种合理的行程,因此,我们直接利用 Hierholzer 算法,输出从起点出发的欧拉路径即可。

时间复杂度 $O(m \times \log m)$,空间复杂度 $O(m)$。其中 $m$ 是边的数量。

<!-- tabs:start -->

Expand All @@ -73,56 +79,43 @@ tags:
```python
class Solution:
def findItinerary(self, tickets: List[List[str]]) -> List[str]:
graph = defaultdict(list)

for src, dst in sorted(tickets, reverse=True):
graph[src].append(dst)

itinerary = []

def dfs(airport):
while graph[airport]:
dfs(graph[airport].pop())
itinerary.append(airport)

def dfs(f: str):
while g[f]:
dfs(g[f].pop())
ans.append(f)

g = defaultdict(list)
for f, t in sorted(tickets, reverse=True):
g[f].append(t)
ans = []
dfs("JFK")

return itinerary[::-1]
return ans[::-1]
```

#### Java

```java
class Solution {
void dfs(Map<String, Queue<String>> adjLists, List<String> ans, String curr) {
Queue<String> neighbors = adjLists.get(curr);
if (neighbors == null) {
ans.add(curr);
return;
}
while (!neighbors.isEmpty()) {
String neighbor = neighbors.poll();
dfs(adjLists, ans, neighbor);
}
ans.add(curr);
return;
}
private Map<String, List<String>> g = new HashMap<>();
private List<String> ans = new ArrayList<>();

public List<String> findItinerary(List<List<String>> tickets) {
Map<String, Queue<String>> adjLists = new HashMap<>();
Collections.sort(tickets, (a, b) -> b.get(1).compareTo(a.get(1)));
for (List<String> ticket : tickets) {
String from = ticket.get(0);
String to = ticket.get(1);
if (!adjLists.containsKey(from)) {
adjLists.put(from, new PriorityQueue<>());
}
adjLists.get(from).add(to);
g.computeIfAbsent(ticket.get(0), k -> new ArrayList<>()).add(ticket.get(1));
}
List<String> ans = new ArrayList<>();
dfs(adjLists, ans, "JFK");
dfs("JFK");
Collections.reverse(ans);
return ans;
}

private void dfs(String f) {
while (g.containsKey(f) && !g.get(f).isEmpty()) {
String t = g.get(f).remove(g.get(f).size() - 1);
dfs(t);
}
ans.add(f);
}
}
```

Expand All @@ -132,36 +125,77 @@ class Solution {
class Solution {
public:
vector<string> findItinerary(vector<vector<string>>& tickets) {
unordered_map<string, priority_queue<string, vector<string>, greater<string>>> g;
vector<string> ret;

// Initialize the graph
for (const auto& t : tickets) {
g[t[0]].push(t[1]);
sort(tickets.rbegin(), tickets.rend());
unordered_map<string, vector<string>> g;
for (const auto& ticket : tickets) {
g[ticket[0]].push_back(ticket[1]);
}
vector<string> ans;
auto dfs = [&](auto&& dfs, string& f) -> void {
while (!g[f].empty()) {
string t = g[f].back();
g[f].pop_back();
dfs(dfs, t);
}
ans.emplace_back(f);
};
string f = "JFK";
dfs(dfs, f);
reverse(ans.begin(), ans.end());
return ans;
}
};
```

findItineraryInner(g, ret, "JFK");
#### Go

```go
func findItinerary(tickets [][]string) (ans []string) {
sort.Slice(tickets, func(i, j int) bool {
return tickets[i][0] > tickets[j][0] || (tickets[i][0] == tickets[j][0] && tickets[i][1] > tickets[j][1])
})
g := make(map[string][]string)
for _, ticket := range tickets {
g[ticket[0]] = append(g[ticket[0]], ticket[1])
}
var dfs func(f string)
dfs = func(f string) {
for len(g[f]) > 0 {
t := g[f][len(g[f])-1]
g[f] = g[f][:len(g[f])-1]
dfs(t)
}
ans = append(ans, f)
}
dfs("JFK")
for i := 0; i < len(ans)/2; i++ {
ans[i], ans[len(ans)-1-i] = ans[len(ans)-1-i], ans[i]
}
return
}
```

ret = {ret.rbegin(), ret.rend()};
#### TypeScript

return ret;
```ts
function findItinerary(tickets: string[][]): string[] {
const g: Record<string, string[]> = {};
tickets.sort((a, b) => b[1].localeCompare(a[1]));
for (const [f, t] of tickets) {
g[f] = g[f] || [];
g[f].push(t);
}

void findItineraryInner(unordered_map<string, priority_queue<string, vector<string>, greater<string>>>& g, vector<string>& ret, string cur) {
if (g.count(cur) == 0) {
// This is the end point
ret.push_back(cur);
return;
} else {
while (!g[cur].empty()) {
auto front = g[cur].top();
g[cur].pop();
findItineraryInner(g, ret, front);
}
ret.push_back(cur);
const ans: string[] = [];
const dfs = (f: string) => {
while (g[f] && g[f].length) {
const t = g[f].pop()!;
dfs(t);
}
}
};
ans.push(f);
};
dfs('JFK');
return ans.reverse();
}
```

<!-- tabs:end -->
Expand Down
156 changes: 95 additions & 61 deletions solution/0300-0399/0332.Reconstruct Itinerary/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,13 @@ tags:

<!-- solution:start -->

### Solution 1
### Solution 1: Eulerian Path

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.

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.

The time complexity is $O(m \times \log m)$, and the space complexity is $O(m)$. Here, $m$ is the number of edges.

<!-- tabs:start -->

Expand All @@ -71,56 +77,43 @@ tags:
```python
class Solution:
def findItinerary(self, tickets: List[List[str]]) -> List[str]:
graph = defaultdict(list)

for src, dst in sorted(tickets, reverse=True):
graph[src].append(dst)

itinerary = []

def dfs(airport):
while graph[airport]:
dfs(graph[airport].pop())
itinerary.append(airport)

def dfs(f: str):
while g[f]:
dfs(g[f].pop())
ans.append(f)

g = defaultdict(list)
for f, t in sorted(tickets, reverse=True):
g[f].append(t)
ans = []
dfs("JFK")

return itinerary[::-1]
return ans[::-1]
```

#### Java

```java
class Solution {
void dfs(Map<String, Queue<String>> adjLists, List<String> ans, String curr) {
Queue<String> neighbors = adjLists.get(curr);
if (neighbors == null) {
ans.add(curr);
return;
}
while (!neighbors.isEmpty()) {
String neighbor = neighbors.poll();
dfs(adjLists, ans, neighbor);
}
ans.add(curr);
return;
}
private Map<String, List<String>> g = new HashMap<>();
private List<String> ans = new ArrayList<>();

public List<String> findItinerary(List<List<String>> tickets) {
Map<String, Queue<String>> adjLists = new HashMap<>();
Collections.sort(tickets, (a, b) -> b.get(1).compareTo(a.get(1)));
for (List<String> ticket : tickets) {
String from = ticket.get(0);
String to = ticket.get(1);
if (!adjLists.containsKey(from)) {
adjLists.put(from, new PriorityQueue<>());
}
adjLists.get(from).add(to);
g.computeIfAbsent(ticket.get(0), k -> new ArrayList<>()).add(ticket.get(1));
}
List<String> ans = new ArrayList<>();
dfs(adjLists, ans, "JFK");
dfs("JFK");
Collections.reverse(ans);
return ans;
}

private void dfs(String f) {
while (g.containsKey(f) && !g.get(f).isEmpty()) {
String t = g.get(f).remove(g.get(f).size() - 1);
dfs(t);
}
ans.add(f);
}
}
```

Expand All @@ -130,36 +123,77 @@ class Solution {
class Solution {
public:
vector<string> findItinerary(vector<vector<string>>& tickets) {
unordered_map<string, priority_queue<string, vector<string>, greater<string>>> g;
vector<string> ret;

// Initialize the graph
for (const auto& t : tickets) {
g[t[0]].push(t[1]);
sort(tickets.rbegin(), tickets.rend());
unordered_map<string, vector<string>> g;
for (const auto& ticket : tickets) {
g[ticket[0]].push_back(ticket[1]);
}
vector<string> ans;
auto dfs = [&](auto&& dfs, string& f) -> void {
while (!g[f].empty()) {
string t = g[f].back();
g[f].pop_back();
dfs(dfs, t);
}
ans.emplace_back(f);
};
string f = "JFK";
dfs(dfs, f);
reverse(ans.begin(), ans.end());
return ans;
}
};
```

findItineraryInner(g, ret, "JFK");
#### Go

```go
func findItinerary(tickets [][]string) (ans []string) {
sort.Slice(tickets, func(i, j int) bool {
return tickets[i][0] > tickets[j][0] || (tickets[i][0] == tickets[j][0] && tickets[i][1] > tickets[j][1])
})
g := make(map[string][]string)
for _, ticket := range tickets {
g[ticket[0]] = append(g[ticket[0]], ticket[1])
}
var dfs func(f string)
dfs = func(f string) {
for len(g[f]) > 0 {
t := g[f][len(g[f])-1]
g[f] = g[f][:len(g[f])-1]
dfs(t)
}
ans = append(ans, f)
}
dfs("JFK")
for i := 0; i < len(ans)/2; i++ {
ans[i], ans[len(ans)-1-i] = ans[len(ans)-1-i], ans[i]
}
return
}
```

ret = {ret.rbegin(), ret.rend()};
#### TypeScript

return ret;
```ts
function findItinerary(tickets: string[][]): string[] {
const g: Record<string, string[]> = {};
tickets.sort((a, b) => b[1].localeCompare(a[1]));
for (const [f, t] of tickets) {
g[f] = g[f] || [];
g[f].push(t);
}

void findItineraryInner(unordered_map<string, priority_queue<string, vector<string>, greater<string>>>& g, vector<string>& ret, string cur) {
if (g.count(cur) == 0) {
// This is the end point
ret.push_back(cur);
return;
} else {
while (!g[cur].empty()) {
auto front = g[cur].top();
g[cur].pop();
findItineraryInner(g, ret, front);
}
ret.push_back(cur);
const ans: string[] = [];
const dfs = (f: string) => {
while (g[f] && g[f].length) {
const t = g[f].pop()!;
dfs(t);
}
}
};
ans.push(f);
};
dfs('JFK');
return ans.reverse();
}
```

<!-- tabs:end -->
Expand Down
Loading
Loading