LeetCode BFS/DFS

BFS/DFS专题

目录

BFS/DFS专题

40. Combination Sum II

79. Word Search

109. Convert Sorted List to Binary Search Tree

200. Number of Islands

329. Longest Increasing Path in a Matrix

547. Friend Circles

695. Max Area of Island

 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
                

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值