LeetCode、广度优先例子,python
2018-12-20 21:28 ZpStu 阅读(388) 评论(0) 编辑 收藏 举报真的坑,自己想完全没想到,看了一些大神的博客写出来的。那个列表很坑,不能写在一起。
但作为一名小白还是很欣慰的。
''' 给定一个由 ‘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)