【Python刷题Leetcode】搜索(DFS+BFS)

深度优先(递归) or 宽度优先(队列)

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        if not grid:
            return 0

        # 初始化mark标记数组
        mark = []
        for row in grid:
            mark.append([0 for _ in grid[0]])
        
        # 初始化岛屿数量
        island_num = 0

        # 初始化四个搜索方向:上下左右
        dx = [-1,1,0,0]
        dy = [0,0,-1,1]

        # 方法一:深度优先搜索
        def DFS(x,y):
            mark[x][y]=1
            for i in range(4):
                # 搜索四个方向
                newx, newy = x+dx[i], y+dy[i]
                if newx<0 or newx>=len(grid) or newy<0 or newy>=len(grid[0]): # 坐标越界
                    continue
                if mark[newx][newy]==0 and grid[newx][newy]=='1': # 坐标为陆地且没被搜索
                    DFS(newx, newy)
        
        # 方法二:宽度优先搜索
        def BFS(x,y):
            Q = [] # 队列 存[x,y]坐标对儿
            Q.append([x,y])
            mark[x][y]=1

            while Q:
                xy = Q.pop(0)
                curx, cury = xy[0], xy[1]  # 读取队头坐标并遍历四个方向
                for i in range(4):
                    newx, newy = curx+dx[i], cury+dy[i]
                    if newx<0 or newx>=len(grid) or newy<0 or newy>=len(grid[0]): # 坐标越界
                        continue
                    if mark[newx][newy]==0 and grid[newx][newy]=='1': # 坐标为陆地且没被搜索
                        Q.append([newx,newy])
                        mark[newx][newy]=1

        # 整体算法流程:遍历每个陆地节点 若没被mark则DFS或者BFS
        for row in range(len(grid)):
            for col in range(len(grid[0])):
                if mark[row][col]==0 and grid[row][col]=='1':
                    # DFS(row,col)
                    BFS(row,col)

                    island_num+=1
        
        return island_num

(但用python过不了)

class Solution:
    def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
        # endWord不在词典中 无法转换
        if endWord not in wordList:
            return 0
        
        # 判断两个单词是否能相互转换(只有一个字母不同)
        def connect(word1, word2):
            num = 0
            for i in range(len(word1)):
                # 注意这里不能写Word1[i] not in word2[i] 比如abc和bcd虽然只有一个字母不同 但各个位置都不同
                if word1[i] != word2[i]:
                    num+=1
                if num>1:
                    return False
            return num==1
        
        # 构造单词之间的转换图(用邻接矩阵 | 记得把beginWord也加进wordList)
        def construct_graph(beginWord, endWord, wordList):
            graph = {}
            if beginWord not in wordList:
                wordList.append(beginWord)
            # 构造key
            for word in wordList:
                graph[word] = []
            # 构造value 无向图 两两比较
            for i in range(len(wordList)):
                for j in range(i+1, len(wordList)):
                    if connect(wordList[i], wordList[j]):
                        graph[wordList[i]].append(wordList[j])
                        graph[wordList[j]].append(wordList[i])
            return graph
        
        # 宽搜
        def DFS(beginWord, endWord, graph):
            Q = []
            visit = []

            Q.append([beginWord,1])
            visit.append(beginWord)
            
            while Q:
                node, step = Q[0][0], Q[0][1]
                Q.pop(0)
                
                # 找到终点 返回步数 结束
                if node==endWord:
                    return step

                # 否则宽搜该点的邻接点 分别加入Q和visit
                for each in graph[node]:
                    if each not in visit:
                        Q.append([each, step+1])
                        visit.append(each)
            
            return 0

        graph = construct_graph(beginWord, endWord, wordList)
        return DFS(beginWord, endWord, graph)

class Solution:
    def makesquare(self, nums: List[int]) -> bool:
        # 优化1:nums总和不能被4整除
        square = sum(nums)
        if not nums or square%4!=0:
            return False
        # 优化2:按从大到小排序
        nums = sorted(nums, reverse=True)
        
        # 初始化4个桶 存储4条边的总和
        bucket = [0,0,0,0]
        
        # DFS:放置第i根火柴(边长为target)
        def generate(i, target):
            # 遍历完所有的火柴了
            if i>len(nums)-1:
                return bucket[0]==bucket[1]==bucket[2]==bucket[3]==target
            # 分别从4个桶里放火柴
            for buc in range(4):
                # 如果放入桶里长度超了 换下一个桶
                if bucket[buc]+nums[i]>target: 
                    continue
                bucket[buc]+=nums[i]
                if generate(i+1, target):
                    return True
                bucket[buc]-=nums[i]

            # 四个桶都放完了 都没返回True
            return False

        # 开始忘写return了
        return generate(i=0, target=square/4)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值