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 0cols = len(grid[0])visited = [[False for _ in range(cols)] for _ in range(rows)]DIRECTION = ((1,0),(-1,0),(0,1),(0,-1))count = 0def isArea(x,y):return x>=0 and y>=0 and x<=rows-1 and y<=cols-1def dfs(i,j):visited[i][j] = Truefor 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+=1return count
BFS
主函数差不多,遍历函数用一个队列来维护了和当前岛屿连接的岛屿,注意DFS只需要向下或者向右,BFS需要把上下左右都加进来查看
from collections import dequeclass 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=0def inArea(x,y):return x>=0 and y>=0 and x<rows and y<colsdef 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+=1return 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 leafleft, how many left ( leftright, how many right ) left'''if left==0 and right==0:res.append(cur_str)returnif right<left:returnif 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 leafleft, how many left ( leftright, how many right ) left'''if left==n and right==n:res.append(cur_str)returnif right>left:returnif 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 dequeclass Solution:def longestIncreasingPath(self, matrix: List[List[int]]) -> int:if not matrix:return 0rows, 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 indegreesfor 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]+=1queue = deque()# 入度为0的坐标进入队列for i in range(rows):for j in range(cols):if indegrees[i][j] == 0:queue.append((i,j))res = 0while queue:# 每一层遍历 res+1res += 1for _ 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] -= 1if indegrees[new_x][new_y] == 0:queue.append((new_x,new_y))return res
从最小的数字开始,遍历每个点附近的四个点, 取这四个点里(1.没有出界,2.值比当前点小)的当前路径最长的,然后这个点的路径就是那个附近最长路径+1, 如果附近四个点都比当前点大,那么这个点就是一个起始点,最长路径为1
from collections import dequeclass Solution:def longestIncreasingPath(self, matrix: List[List[int]]) -> int:if not matrix:return 0rows, 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<colspoints = sorted([[matrix[i][j], (i,j)] for i in range(rows) for j in range(cols)])res = 0for point in points:value = point[0]x, y = point[1]max_path = 0for 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+1res = 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 boardrows, 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<colsdef 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 boaderfor j in range(cols):if board[0][j] == 'O':dfs(0,j)if board[rows-1][j] == 'O':dfs(rows-1, j)# left&right boaderfor 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 heapqclass Solution:def swimInWater(self, grid: List[List[int]]) -> int:if not grid:return 0rows, 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 = locvisited[x][y] = Trueif x == rows-1 and y == cols-1:return highfor 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)) )
