Skip to content

Commit d5e402d

Browse files
committed
D. J.:
- Added the leetcode problem and solution for 127, 130, 133, 200, 207, 210, 399, 433 and 909
1 parent 30ef332 commit d5e402d

19 files changed

+746
-1
lines changed

awesome_python_leetcode/_117_populating_next_right_pointers_in_each_node_II.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ def __init__(
1717
self.next = next
1818

1919
def __eq__(self, other: List[int]) -> bool:
20-
"""Compare the pointers to the next node."""
2120
if self is None or other is None:
2221
return True
2322

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import collections
2+
from typing import List
3+
4+
5+
class Solution:
6+
"""Base class for all LeetCode Problems."""
7+
8+
def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
9+
"""
10+
A transformation sequence from word beginWord to word endWord using a dictionary
11+
wordList is a sequence of words beginWord -> s1 -> s2 -> ... -> sk such that:
12+
- Every adjacent pair of words differs by a single letter.
13+
- Every si for 1 <= i <= k is in wordList. Note that beginWord does not need to
14+
be in wordList.
15+
- sk == endWord
16+
17+
Given two words, beginWord and endWord, and a dictionary wordList, return the
18+
number of words in the shortest transformation sequence from beginWord to
19+
endWord, or 0 if no such sequence exists.
20+
"""
21+
# Create adjacency matrix
22+
adj = collections.defaultdict(list)
23+
wordList.append(beginWord)
24+
for word in wordList:
25+
for j in range(len(word)):
26+
pattern = word[:j] + "*" + word[j + 1 :]
27+
adj[pattern].append(word)
28+
29+
def bfs(src, target):
30+
queue = [(src, 1)]
31+
visited = {src}
32+
while queue:
33+
word, mutations = queue.pop(0)
34+
if word == target:
35+
return mutations
36+
for j in range(len(word)):
37+
pattern = word[:j] + "*" + word[j + 1 :]
38+
for next_word in adj[pattern]:
39+
if next_word not in visited:
40+
queue.append((next_word, mutations + 1))
41+
visited.add(next_word)
42+
return 0
43+
44+
return bfs(beginWord, endWord)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from typing import List
2+
3+
4+
class Solution:
5+
"""Base class for all LeetCode Problems."""
6+
7+
def solve(self, board: List[List[str]]) -> None:
8+
"""
9+
You are given an m x n matrix board containing letters 'X' and 'O', capture
10+
regions that are surrounded:
11+
- Connect: A cell is connected to adjacent cells horizontally or vertically.
12+
- Region: To form a region connect every 'O' cell.
13+
- Surround: The region is surrounded with 'X' cells if you can connect the
14+
region with 'X' cells and none of the region cells are on the edge of the board.
15+
16+
To capture a surrounded region, replace all 'O's with 'X's in-place within the
17+
original board. You do not need to return anything.
18+
"""
19+
rows, cols = len(board), len(board[0])
20+
21+
def capture(r: int, c: int):
22+
if r < 0 or c < 0 or r >= rows or c >= cols or board[r][c] != "O":
23+
return
24+
board[r][c] = "T"
25+
capture(r - 1, c)
26+
capture(r + 1, c)
27+
capture(r, c - 1)
28+
capture(r, c + 1)
29+
30+
# Capture non surrounded regions (O -> T)
31+
for r in range(rows):
32+
for c in range(cols):
33+
if board[r][c] == "O" and (r in [0, rows - 1] or c in [0, cols - 1]):
34+
capture(r, c)
35+
36+
# Replace surrounded regions (O -> X)
37+
for r in range(rows):
38+
for c in range(cols):
39+
if board[r][c] == "O":
40+
board[r][c] = "X"
41+
42+
# Replace non surrounded regions (T -> O)
43+
for r in range(rows):
44+
for c in range(cols):
45+
if board[r][c] == "T":
46+
board[r][c] = "O"
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import collections
2+
from typing import List, Optional, Dict
3+
4+
5+
class Node:
6+
def __init__(self, val=0, neighbors=None):
7+
self.val = val
8+
self.neighbors = neighbors if neighbors is not None else []
9+
10+
def __hash__(self) -> int:
11+
return self.val
12+
13+
def __eq__(self, other: Optional["Node"]) -> bool:
14+
if self is None and other is None:
15+
return True
16+
elif self is None:
17+
return False
18+
elif other is None:
19+
return False
20+
adj1 = self.adj_list()
21+
adj2 = other.adj_list()
22+
return adj1 == adj2
23+
24+
def adj_list(self) -> Dict[int, List[int]]:
25+
"""Return the adjacency list of the graph."""
26+
adj = collections.defaultdict(list)
27+
queue = [self]
28+
visited = {self.val}
29+
while queue:
30+
node = queue.pop(0)
31+
for neighbor in node.neighbors:
32+
if neighbor.val not in visited:
33+
adj[node.val].append(neighbor.val)
34+
queue.append(neighbor)
35+
visited.add(neighbor.val)
36+
return adj
37+
38+
@staticmethod
39+
def build(edges: List[List[int]]) -> Optional["Node"]:
40+
"""Build a graph from an adjacency list."""
41+
if not edges:
42+
return None
43+
44+
nodes = {}
45+
for i in range(len(edges)):
46+
if i not in nodes:
47+
nodes[i + 1] = Node(i + 1)
48+
for j in edges[i]:
49+
if j not in nodes:
50+
nodes[j] = Node(j)
51+
nodes[i + 1].neighbors.append(nodes[j])
52+
return nodes[1]
53+
54+
55+
class Solution:
56+
"""Base class for all LeetCode Problems."""
57+
58+
def cloneGraph(self, node: Optional["Node"]) -> Optional["Node"]:
59+
"""
60+
Given a reference of a node in a connected undirected graph.
61+
62+
Return a deep copy (clone) of the graph.
63+
64+
Each node in the graph contains a value (int) and a list (List[Node]) of its
65+
neighbors.
66+
67+
class Node {
68+
public int val;
69+
public List<Node> neighbors;
70+
}
71+
72+
73+
Test case format:
74+
75+
For simplicity, each node's value is the same as the node's index (1-indexed).
76+
For example, the first node with val == 1, the second node with val == 2, and so
77+
on. The graph is represented in the test case using an adjacency list.
78+
79+
An adjacency list is a collection of unordered lists used to represent a finite
80+
graph. Each list describes the set of neighbors of a node in the graph.
81+
82+
The given node will always be the first node with val = 1. You must return the
83+
copy of the given node as a reference to the cloned graph.
84+
"""
85+
86+
if node is None:
87+
return None
88+
89+
# Create all new nodes (without neighbors)
90+
old_to_copy = {None: None}
91+
queue = [node]
92+
visited = {node}
93+
while queue:
94+
cur = queue.pop(0)
95+
copy = Node(cur.val)
96+
old_to_copy[cur] = copy
97+
for nxt in cur.neighbors:
98+
if nxt not in visited:
99+
queue.append(nxt)
100+
visited.add(nxt)
101+
102+
# Add all neighbors to new nodes
103+
queue = [node]
104+
visited = {node}
105+
while queue:
106+
cur = queue.pop(0)
107+
copy = old_to_copy[cur]
108+
copy.neighbors = [old_to_copy[nxt] for nxt in cur.neighbors]
109+
for nxt in cur.neighbors:
110+
if nxt not in visited:
111+
queue.append(nxt)
112+
visited.add(nxt)
113+
114+
return old_to_copy[node]
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from typing import List, Tuple
2+
3+
4+
class Solution:
5+
"""Base class for all LeetCode Problems."""
6+
7+
def numIslands(self, grid: List[List[str]]) -> int:
8+
"""
9+
Given an m x n 2D binary grid grid which represents a map of '1's (land) and
10+
0's (water), return the number of islands.
11+
12+
An island is surrounded by water and is formed by connecting adjacent lands
13+
horizontally or vertically. You may assume all four edges of the grid are all
14+
surrounded by water.
15+
"""
16+
y, x = len(grid), len(grid[0])
17+
num_islands = 0
18+
visited = set()
19+
20+
def neighbors(pos: Tuple[int, int]) -> List[Tuple[int, int]]:
21+
next_pos = [
22+
(pos[0] - 1, pos[1]),
23+
(pos[0], pos[1] - 1),
24+
(pos[0] + 1, pos[1]),
25+
(pos[0], pos[1] + 1),
26+
]
27+
neighbors = [
28+
p
29+
for p in next_pos
30+
if p[0] >= 0
31+
and p[1] >= 0
32+
and p[0] < x
33+
and p[1] < y
34+
and grid[p[1]][p[0]] == "1"
35+
and p not in visited
36+
]
37+
return neighbors
38+
39+
for x_ in range(x):
40+
for y_ in range(y):
41+
if grid[y_][x_] != "1" or (x_, y_) in visited:
42+
continue
43+
# BFS
44+
queue = [(x_, y_)]
45+
visited.add((x_, y_))
46+
while queue:
47+
pos = queue.pop(0)
48+
next_pos = neighbors(pos)
49+
for p in next_pos:
50+
visited.add(p)
51+
queue.append(p)
52+
num_islands += 1
53+
return num_islands
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import collections
2+
from typing import List
3+
4+
5+
class Solution:
6+
"""Base class for all LeetCode Problems."""
7+
8+
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
9+
"""
10+
There are a total of numCourses courses you have to take, labeled from 0 to
11+
numCourses - 1. You are given an array prerequisites where prerequisites[i] =
12+
[ai, bi] indicates that you must take course bi first if you want to take course
13+
ai.
14+
15+
- For example, the pair [0, 1], indicates that to take course 0 you have to
16+
first take course 1.
17+
18+
Return true if you can finish all courses. Otherwise, return false.
19+
"""
20+
adj = collections.defaultdict(list)
21+
for course1, course2 in prerequisites:
22+
adj[course1].append(course2)
23+
visited = set()
24+
25+
def dfs(course: int) -> bool:
26+
if course in visited:
27+
return False
28+
if not adj[course]:
29+
return True
30+
visited.add(course)
31+
for next_course in adj[course]:
32+
if not dfs(next_course):
33+
return False
34+
visited.remove(course)
35+
adj[course] = []
36+
return True
37+
38+
for course in range(numCourses):
39+
if not dfs(course):
40+
return False
41+
return True
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import collections
2+
from typing import List
3+
4+
5+
class Solution:
6+
"""Base class for all LeetCode Problems."""
7+
8+
def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
9+
"""
10+
There are a total of numCourses courses you have to take, labeled from 0 to
11+
numCourses - 1. You are given an array prerequisites where prerequisites[i] =
12+
[ai, bi] indicates that you must take course bi first if you want to take
13+
course ai.
14+
15+
- For example, the pair [0, 1], indicates that to take course 0 you have to
16+
first take course 1.
17+
18+
Return the ordering of courses you should take to finish all courses. If there
19+
are many valid answers, return any of them. If it is impossible to finish all
20+
courses, return an empty array.
21+
"""
22+
adj = collections.defaultdict(list)
23+
for course1, course2 in prerequisites:
24+
adj[course1].append(course2)
25+
26+
visited, cycle, order = set(), set(), []
27+
28+
def dfs(course: int) -> bool:
29+
if course in cycle:
30+
return False
31+
if course in visited:
32+
return True
33+
34+
cycle.add(course)
35+
for next_course in adj[course]:
36+
if not dfs(next_course):
37+
return False
38+
cycle.remove(course)
39+
visited.add(course)
40+
order.append(course)
41+
return True
42+
43+
for course in range(numCourses):
44+
if not dfs(course):
45+
return []
46+
return order

0 commit comments

Comments
 (0)