BFS/DFS专题
目录
109. Convert Sorted List to Binary Search Tree
329. Longest Increasing Path in a Matrix
698. Partition to K Equal Sum Subsets
1254. Number of Closed Islands
40. Combination Sum II
题目链接:https://leetcode.com/problems/combination-sum-ii/
这是一个0/1背包+dfs问题,每次选择放入当前元素,或者不放入。
class Solution:
def combinationSum2(self, nums: List[int], t: int) -> List[List[int]]:
d={}
def dfs(i,target):
if i==len(nums):
return []
elif target<=0:
return []
elif (i,target) in d.keys():
return d[(i,target)]
else:
res=[]
x=dfs(i+1,target-nums[i])
if x:
print(i,target,x)
res= [[nums[i]]+k for k in x]
elif nums[i]==target:
res=[[nums[i]]]
res+=dfs(i+1,target)
d[(i,target)]=res
return res
res=dfs(0,t)
# print(d)
c={}
for i in res:
c[tuple(sorted(i))]=c.get(tuple(sorted(i)),0)+1
return list(c.keys())
79. Word Search
题目链接:https://leetcode.com/problems/word-search/
dfs(i,j,s)返回的结果代表从当前位置(i,j)出发,是否能得到s字符串。首先,s如果为空,则必定可以满足,返回True;如果当前位置是非法的或者已经访问过了,则返回false;如果board[i][j]!=w[0],这样也是False;最后的一种合理情况是board[i][j]==w[0],首先将visited[i][j]设置为1,然后对(i,j)的相邻位置遍历,如果能得到True,则直接返回True,否则无法得到True的结果,则将visited[i][j]设置为0,返回False。
class Solution(object):
def exist(self, b, w):
"""
:type board: List[List[str]]
:type word: str
:rtype: bool
"""
m,n=len(b),len(b[0])
visited=[[0]*n for _ in range(m)]
move=[(1,0),(-1,0),(0,1),(0,-1)]
def dfs(i,j,s):
if not s:
return True
elif i<0 or i>=m or j<0 or j>=n:
return False
elif visited[i][j]:
return False
elif b[i][j]!=s[0]:
return False
else:
visited[i][j]=1
for step in move:
x,y=i+step[0],j+step[1]
# if 0<=x<m and 0<=y<n and not visited[x][y]:
if not dfs(x,y,s[1:]):
pass
else:
return True
visited[i][j]=0
return False
for i in range(m):
for j in range(n):
if dfs(i,j,w):
return True
return False
109. Convert Sorted List to Binary Search Tree
题目链接:https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def sortedListToBST(self, head):
"""
:type head: ListNode
:rtype: TreeNode
"""
data=[]
while head:
data.append(head.val)
head=head.next
# print(data)
l=len(data)
def make_tree(left,right):
if left==right:
return TreeNode(data[left])
elif left>right:
return None
middle=(left+right)//2
root=TreeNode(data[middle])
root.left=make_tree(left,middle-1)
root.right=make_tree(middle+1,right)
return root
return make_tree(0,l-1)
200. Number of Islands
题目链接:https://leetcode.com/problems/number-of-islands/
水题,队列+BFS即可
class Solution(object):
def numIslands(self, grid):
"""
:type grid: List[List[str]]
:rtype: int
"""
if not grid:
return 0
m,n=len(grid),len(grid[0])
if not n:
return 0
_pos=[(1,0),(0,1),(-1,0),(0,-1)]
visited=[[0]*n for _ in range(m)]
islands=[]
while 1:
row,col=-1,-1
for i in range(m):
for j in range(n):
if grid[i][j]== '1' and not visited[i][j]:
row,col=i,j
break
if row == -1 and col == -1:
break
x=[(row,col)]
island=[(row,col)]
for pt in x:
visited[pt[0]][pt[1]]=1
for p in _pos:
pos_x,pos_y=pt[0]+p[0],pt[1]+p[1]
if 0<= pos_x <m and 0<= pos_y <n and not visited[pos_x][pos_y] and grid[pos_x][pos_y]== '1':
visited[pos_x][pos_y]=1
island.append((pos_x,pos_y))
x.append((pos_x,pos_y))
islands.append(island)
print(islands)
return len(islands)
329. Longest Increasing Path in a Matrix
题目链接:https://leetcode.com/problems/longest-increasing-path-in-a-matrix/
class Solution(object):
def __init__(self):
self.max_len=0
self.d={}
def longestIncreasingPath(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: int
"""
def dfs(x,y,prev):
if x< 0 or x>=len(matrix) or y<0 or y>=len(matrix[0]) or matrix[x][y]<=prev:
return 0
if self.d.__contains__((x,y)):
return self.d[(x,y)]
# res=1
res=max(dfs(x+1,y,matrix[x][y]),dfs(x-1,y,matrix[x][y]),
dfs(x,y+1,matrix[x][y]),dfs(x,y-1,matrix[x][y]))+1
self.d[(x,y)]=res
self.max_len=max(res,self.max_len)
print(x,y,self.max_len,res)
return res
for i in range(len(matrix)):
for j in range(len(matrix[0])):
_=dfs(i,j,-2**30)
return self.max_len
547. Friend Circles
题目链接:https://leetcode.com/problems/friend-circles/
Given a N*N matrix M representing the friend relationship between students in the class. If M[i][j] = 1, then the ith and jth students are direct friends with each other, otherwise not. And you have to output the total number of friend circles among all the students.
Input:
[[1,1,0],
[1,1,0],
[0,0,1]]
Output: 2
Explanation:The 0th and 1st students are direct friends, so they are in a friend circle.
The 2nd student himself is in a friend circle. So return 2.
思路是对于矩阵的一侧进行处理,遍历所有students,设置visited数组存储students的访问情况,对于student i,如果student j没有被处理过,而且m[k][j]==1,那么接着深度遍历student j,将返回的dfs(j)和[i]拼接在一起,作为结果。visited的意义在于避免无限递归。
class Solution(object):
def findCircleNum(self, m):
"""
:type M: List[List[int]]
:rtype: int
"""
visited=[]
n=len(m)
visited=[0]*n
# circles=[]
def dfs(k):
circle=[k]
visited[k]=1
for j in range(0,n):
if m[k][j] and not visited[j]:
circle+=dfs(j)
return set(circle)
res=[dfs(0)]
for i in range(1,n):
flag=0
for t in res:
if i in t:
flag=1
break
if flag==0:
res.append(dfs(i))
print(res)
return len(res)
695. Max Area of Island
题目链接:https://leetcode.com/problems/max-area-of-island/
利用队列实现BFS,当队列不为空时,出列一个位置,对该位置的四个相邻位置,判断是否已经访问过,值是否为1,若都满足,则放入队列,并设置状态为已访问。
import Queue
class Solution(object):
def maxAreaOfIsland(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
# grid = np.array(grid)
m, n = len(grid), len(grid[0])
visited = [[0]*n for _ in range(m)]
clusters = []
while 1:
row, col = -1, -1
for i in range(m):
for j in range(n):
if grid[i][j] and not visited[i][j]:
row, col = i, j
break
if row == -1 and col == -1:
break
q = Queue.Queue()
q.put((row, col))
cluster = [(row, col)]
while not q.empty():
i, j = q.get()
visited[i][j] = 1
neighbors = [[1, 0], [0, 1],
[-1, 0], [0, -1]]
neighbors_pos = [[x[0]+i, x[1]+j] for x in neighbors]
for (i, j) in neighbors_pos:
if 0 <= i < m and 0 <= j < n and not visited[i][j] and grid[i][j]:
q.put((i, j))
visited[i][j] = 1
cluster.append((i, j))
clusters.append(cluster)
l=[len(i) for i in clusters]
print(l)
return max(l) if l else 0
698. Partition to K Equal Sum Subsets
题目链接:https://leetcode.com/problems/partition-to-k-equal-sum-subsets/
题目思路:用一个数组存每个元素被访问的状态,当当前和为target时,递归调用dfs(k-1,0,0),这样被访问过的元素不会再访问。如果对一个数值,找不到可以等于target的元素,就会放回false,那么被标记为访问的元素又会被标记为未访问。
class Solution(object):
def canPartitionKSubsets(self, nums, a):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
target=sum(nums)//a
if sum(nums)%a!=0 or a>sum(nums):
return False
visited=[0]*len(nums)
# print(target)
def dfs(k,index,cur_sum):
if cur_sum==target and k==1:
return True
if cur_sum==target:
return dfs(k-1,0,0)
else:
for i in range(index,len(nums)):
if cur_sum+nums[i]<=target and not visited[i]:
visited[i]=1
if dfs(k,i+1,cur_sum+nums[i]):
return True
visited[i]=0
return False
return dfs(a,0,0)
1254. Number of Closed Islands
题目链接:https://leetcode.com/problems/number-of-closed-islands/
思路是先dfs得到所有的岛,然后对所有的岛判断,是不是所有的点都在边界以内,如果是的,那么这个岛就符合条件。
class Solution(object):
def closedIsland(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
m,n=len(grid),len(grid[0])
visited=[[0]*n for _ in range(m)]
pp=[(1,0),(-1,0),(0,1),(0,-1)]
islands=[]
while 1:
i,j=-1,-1
for k in range(m*n):
if not visited[k//n][k%n] and not grid[k//n][k%n]:
i,j=k//n,k%n
break
if i ==-1 and j==-1:
break
visited[i][j]=1
res=[(i,j)]
for pt in res:
i,j=pt[0],pt[1]
for p in pp:
x,y=i+p[0],j+p[1]
if 0<=x<m and 0<=y<n and not visited[x][y] and not grid[x][y]:
visited[x][y]=1
res.append((x,y))
islands.append(res)
res=0
for island in islands:
flag=1
for pt in island:
x,y=pt[0],pt[1]
if x==0 or x==m-1 or y==0 or y==n-1:
flag=0
break
res+=flag
return res