LeetCode广度优先算法的题

真的坑,自己想完全没想到,看了一些大神的博客写出来的。那个列表很坑,不能写在一起。
但作为一名小白还是很欣慰的。

'''
给定一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,计算岛屿的数量。
一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。
你可以假设网格的四个边均被水包围
'''
# 考虑这个题目,计算岛屿数量,也就是单独岛屿的数量,
# 两个以上的1 连在一起的算是一个岛屿,那么也就是只要找到单独一块的岛屿就行了,
# 这样就很好理解了!
lt1 = [
  [1, 1, 0, 0, 0],
  [0, 1, 0, 0, 1],
  [0, 0, 0, 1, 1],
  [0, 0, 0, 0, 0],
  [0, 0, 0, 0, 1]
]
lt2 = [
  [1, 1, 1, 1, 0],
  [1, 1, 0, 1, 0],
  [0, 0, 0, 1, 1],
  [0, 0, 0, 0, 0],
  [0, 0, 0, 0, 1]
]
class Solution:
    def munIsLand(self, grid):
        n = len(grid)
        if n == 0:
            return '地图为空'
        m = len(grid[0])
        if m == 0:
            return '地图为空'
        # 当找到岛屿的时候就把下面变量自+1
        res = 0
        # 开始遍历寻找第一个 1 ,(岛屿)
        for i in range(n):
            for j in range(m):
                # 判断是不是一个岛屿
                if grid[i][j] == 1:
                    res = res + 1
                    # 这个时候还要判断与它连接在一起的1,
                    # 毕竟一家人要整整齐齐的,所以递归寻找连在一起的所有岛屿,
                    # 同时需要注意的是,一个岛屿你只能遍历一次,
                    # 所以打个标识,让寻找到的岛屿变成0
                    self.change(grid, i, j)
        return res
    def change(self, grid, i, j):
        grid[i][j] = 0
        # 判断这个岛屿上下左右的方向
        # 判断上方字符
        if i > 0 and grid[i - 1][j] == 1:
            self.change(grid, i - 1, j)
        # 判断左方字符
        if j > 0 and grid[i][j - 1] == 1:
            self.change(grid, i, j - 1)
        # 判断下方字符
        if i < len(grid) - 1 and grid[i + 1][j] == 1:
            self.change(grid, i + 1, j)
        # 判断右方字符
        if j < len(grid[0]) - 1 and grid[i][j + 1] == 1:
            self.change(grid, i, j + 1)

ss = Solution()
print(ss.munIsLand(lt1))
print(ss.munIsLand(lt2))
  • 关于密码锁问题
import collections

class Solution:
    '''
    算法思想:
    这也是一道很有意思的题,其实本质就是个迷宫遍历的问题,只不过相邻位置不再是上下左右四个位置,
    而是四位数字每个都加一减一,总共有八个相邻的位置。与经典BFS遍历迷宫解法唯一不同的就是找下一个位置的地方,
    这里我们要遍历四位数字的每一位,然后分别加1减1,我们用j从-1遍历到1,遇到0跳过,也就是实现了加1减1的过程。
    然后我们要计算要更新位上的数字,为了处理9加1变0,和0减1变9的情况,我们统一给该位数字加上个10,然后再加或减1,
    最后再对10取余即可。
    如果此时新生成的字符串等于target了,直接返回结果res,否则我们看如果该字符串不在死锁集合里,
    且之前没有遍历过,那么加入队列queue中,之后将该字符串加入visited集合中即可。注意这里在while循环中,
    由于要一层一层的往外扩展
    '''
    def openLock(self, deadends, target):
        deadset = set(deadends)
        if (target in deadset) or ("0000" in deadset):
            return -1
        # 之前没有遍历过加入队列之中
        que = collections.deque()
        que.append("0000")
        # 然后在把他加入集合里面
        visited = set(["0000"])
        step = 0
        # 这个要一层层的向外扩张
        while que:
            # 每次循环寻找次数都会+1
            step += 1
            # 计算每次循环时,队列中原书的个数
            size = len(que)
            # 在新的元素基础上开始遍历
            for i in range(size):
                # 依次取出  0 1 2 3 4 ... 赋值给point指针
                point = que.popleft()
                # 第二次循环,给每个滚轮上面操作
                for j in range(4):
                    # 第三次循环,设置 +1, -1,让每个滚轮加+、减一
                    for k in range(-1, 2, 2):
                        # 程序执行到这里,point已经执行完毕了,也就是point就等于queue,这里是把point赋给newPoint
                        newPoint = [i for i in point]
                        # 让这个新赋值的队列中,给每个元素加减1操作,并且这里有-1-9,10-0的转换操作
                        newPoint[j] = chr((ord(newPoint[j]) - ord('0') + k) % 10 + ord('0'))
                        # 这里把列表里面['1','2','3','4']转换为'1234'
                        newPoint = "".join(newPoint)
                        # 判断这个字符串是不是目标字符串
                        if newPoint == target:
                            return step
                        # 如果这个字符串不再死锁或者集合字符串中, 就跳过这次循环
                        if (newPoint in deadset) or (newPoint in visited):
                            continue
                        # 把这个字符串加入到队列queue中
                        que.append(newPoint)
                        # 把这个字符串加入到集合中
                        visited.add(newPoint)
        return -1

a = Solution()
ret = a.openLock('1515', '1523')
print(ret)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值