200. 岛屿数量
https://leetcode-cn.com/problems/number-of-islands/
This question can be solved by DFS, BFS, Union-Find, I only practiced DFS and Union-Find
这道题也可以不用visited函数,在原来grid上修改,但是如果面试中,需要询问是否可以修改原数组
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
rows = len(grid)
if rows==0:
return 0
cols = len(grid[0])
visited = [[False for _ in range(cols)] for _ in range(rows)]
DIRECTION = ((1,0),(-1,0),(0,1),(0,-1))
count = 0
def isArea(x,y):
return x>=0 and y>=0 and x<=rows-1 and y<=cols-1
def dfs(i,j):
visited[i][j] = True
for k in range(4):
x = i + DIRECTION[k][0]
y = j + DIRECTION[k][1]
if isArea(x,y) and not visited[x][y] and grid[x][y]=='1':
dfs(x,y)
for i in range(rows):
for j in range(cols):
if not visited[i][j] and grid[i][j]=='1':
dfs(i,j)
count+=1
return count
BFS
主函数差不多,遍历函数用一个队列来维护了和当前岛屿连接的岛屿,注意DFS只需要向下或者向右,BFS需要把上下左右都加进来查看
from collections import deque
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
rows =len(grid)
cols =len(grid[0])
DIRECTION = ((1,0),(0,1),(-1,0),(0,-1))
count=0
def inArea(x,y):
return x>=0 and y>=0 and x<rows and y<cols
def bfs(x,y):
queue = deque()
queue.append([x,y])
while queue:
i,j = queue.popleft()
if inArea(i,j) and grid[i][j]=='1':
grid[i][j]='0'
for k in range(4):
queue.append([i+DIRECTION[k][0],j+DIRECTION[k][1]])
for i in range(rows):
for j in range(cols):
if grid[i][j]=='1':
bfs(i,j)
count+=1
return count
22. 括号生成
https://leetcode-cn.com/problems/generate-parentheses/
left和right从n开始递减,表示还剩多少个括号留下没用
def generateParenthesis(self, n: int) -> List[str]:
res = []
cur_str = ''
def dfs(cur_str, left, right):
'''
params:
cur_str, the string from root to leaf
left, how many left ( left
right, how many right ) left
'''
if left==0 and right==0:
res.append(cur_str)
return
if right<left:
return
if left > 0:
dfs(cur_str+'(', left-1,right)
if right >0:
dfs(cur_str+')', left, right-1)
dfs(cur_str, n,n)
return res
left和right从0开始,逐渐增加,注意判断条件变成了right要严格小于left,如果大于了就要return
def generateParenthesis(self, n: int) -> List[str]:
res = []
cur_str = ''
def dfs(cur_str, left, right):
'''
params:
cur_str, the string from root to leaf
left, how many left ( left
right, how many right ) left
'''
if left==n and right==n:
res.append(cur_str)
return
if right>left:
return
if left < n:
dfs(cur_str+'(', left+1,right)
if right < n:
dfs(cur_str+')', left, right+1)
dfs(cur_str, 0,0)
return res
剑指 Offer 12. 矩阵中的路径
https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/
329. 矩阵中的最长递增路径
https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/
拓扑排序, 课程表是为了找环,如果有环,说明无法学完全部课程,因为有的课程互为先决条件,导致有环出现。
这道题以数字大小来作为出度入度,是肯定没有环的,要计算的最长路径,那么就是每次把入度为0的作为一层,将这一层点挪去之后,还剩下的入度为0的点就是下一次,加入队列进入下一次循环, 经过多少次循环后再也没有入度为0的点就得到了最长递增路径
from collections import deque
class Solution:
def longestIncreasingPath(self, matrix: List[List[int]]) -> int:
if not matrix:
return 0
rows, cols = len(matrix), len(matrix[0])
DIRECTION = ((1,0),(-1,0),(0,1),(0,-1))
# indegrees每个坐标上的值,是matrix对应坐标位置的入度
indegrees = [[0 for _ in range(cols)] for _ in range(rows)]
def inArea(x,y):
return x>=0 and y>=0 and x<rows and y<cols
# calculate the indegrees
for i in range(rows):
for j in range(cols):
for k in range(4):
new_x = i + DIRECTION[k][0]
new_y = j + DIRECTION[k][1]
if inArea(new_x, new_y) and matrix[i][j] > matrix[new_x][new_y]:
indegrees[i][j]+=1
queue = deque()
# 入度为0的坐标进入队列
for i in range(rows):
for j in range(cols):
if indegrees[i][j] == 0:
queue.append((i,j))
res = 0
while queue:
# 每一层遍历 res+1
res += 1
for _ in range(len(queue)):
x, y = queue.popleft()
for k in range(4):
new_x = x + DIRECTION[k][0]
new_y = y + DIRECTION[k][1]
if inArea(new_x,new_y) and matrix[x][y] < matrix[new_x][new_y]:
indegrees[new_x][new_y] -= 1
if indegrees[new_x][new_y] == 0:
queue.append((new_x,new_y))
return res
从最小的数字开始,遍历每个点附近的四个点, 取这四个点里(1.没有出界,2.值比当前点小)的当前路径最长的,然后这个点的路径就是那个附近最长路径+1, 如果附近四个点都比当前点大,那么这个点就是一个起始点,最长路径为1
from collections import deque
class Solution:
def longestIncreasingPath(self, matrix: List[List[int]]) -> int:
if not matrix:
return 0
rows, cols = len(matrix), len(matrix[0])
DIRECTION = ((1,0),(-1,0),(0,1),(0,-1))
dp = [[0]*cols for _ in range(rows)]
def inArea(x,y):
return x>=0 and y>=0 and x<rows and y<cols
points = sorted([[matrix[i][j], (i,j)] for i in range(rows) for j in range(cols)])
res = 0
for point in points:
value = point[0]
x, y = point[1]
max_path = 0
for k in range(4):
new_x = x + DIRECTION[k][0]
new_y = y + DIRECTION[k][1]
if inArea(new_x, new_y) and matrix[new_x][new_y] < value:
max_path = max(max_path, dp[new_x][new_y])
dp[x][y] = max_path+1
res = max(res, dp[x][y])
return res
130. 被围绕的区域
https://leetcode-cn.com/problems/surrounded-regions/
和边界的O连接的o不变, 其他位置的o都是被围绕的,需要被设置为x
那么dfs bfs 和并查集都可以解决,思路是先处理边界位置的O, 把和边界相连的o都置为,比如#,结束遍历后再重新遍历一次board, 把#置为o,把o置为x
dfs是递归, bfs是用队列
class Solution:
def solve(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
if not board:
return board
rows, cols = len(board), len(board[0])
DIRECTION = ((0,1),(1,0),(0,-1),(-1,0))
ans = []
def inArea(x, y):
return x >= 0 and y>=0 and x<rows and y<cols
def dfs(x, y):
board[x][y] = '#'
for k in range(4):
new_x = x + DIRECTION[k][0]
new_y = y + DIRECTION[k][1]
if inArea(new_x, new_y) and board[new_x][new_y] == 'O':
dfs(new_x, new_y)
# up&bottom boader
for j in range(cols):
if board[0][j] == 'O':
dfs(0,j)
if board[rows-1][j] == 'O':
dfs(rows-1, j)
# left&right boader
for i in range(rows):
if board[i][0] == 'O':
dfs(i,0)
if board[i][cols-1] == 'O':
dfs(i,cols-1)
for i in range(rows):
for j in range(cols):
board[i][j] = 'O' if board[i][j] == '#' else 'X'
return board
778. 水位上升的泳池中游泳
https://leetcode-cn.com/problems/swim-in-rising-water/
优先队列, Python的实现是二叉堆. 相当于flood fill, 类似bfs的思维. 不是贪心只关注当前点周围可以去到的最低的点, 而是当前走过的点里面去找最低的点. 比如一个点如果选择过, 那么这个点的→和↓就会变为可接触的点,并且进入二叉堆heap, 每次我们都选择这些可接触点的最小值,也就是二叉堆的堆顶
import heapq
class Solution:
def swimInWater(self, grid: List[List[int]]) -> int:
if not grid:
return 0
rows, cols = len(grid), len(grid[0])
visited = [[False]*cols for _ in range(rows)]
heap = []
heapq.heappush(heap, (grid[0][0],(0,0)))
high = float('-inf')
DIRECTION = ((1,0), (0,1), (-1,0), (0,-1))
while heap:
height, loc = heapq.heappop(heap)
high = max(high, height)
x, y = loc
visited[x][y] = True
if x == rows-1 and y == cols-1:
return high
for k in range(4):
new_x = x + DIRECTION[k][0]
new_y = y + DIRECTION[k][1]
if 0<=new_x<rows and 0<=new_y<cols and not visited[new_x][new_y]:
heapq.heappush(heap, (grid[new_x][new_y], (new_x, new_y)) )