用队列实现栈

  1. class MyStack:
  2. def __init__(self):
  3. self.queue=collections.deque()
  4. def push(self, x: int) -> None:
  5. size=len(self.queue)
  6. self.queue.append(x)
  7. for _ in range(size):
  8. self.queue.append(self.queue.popleft())
  9. def pop(self) -> int:
  10. return self.queue.popleft()
  11. def top(self) -> int:
  12. return self.queue[0]
  13. def empty(self) -> bool:
  14. return len(self.queue)==0

设计循环队列

  1. class MyCircularQueue:
  2. def __init__(self, k: int):
  3. """
  4. Initialize your data structure here. Set the size of the queue to be k.
  5. """
  6. self.queue = [0]*k
  7. self.headIndex = 0
  8. self.count = 0
  9. self.capacity = k
  10. def enQueue(self, value: int) -> bool:
  11. """
  12. Insert an element into the circular queue. Return true if the operation is successful.
  13. """
  14. if self.count == self.capacity:
  15. return False
  16. self.queue[(self.headIndex + self.count) % self.capacity] = value
  17. self.count += 1
  18. return True
  19. def deQueue(self) -> bool:
  20. """
  21. Delete an element from the circular queue. Return true if the operation is successful.
  22. """
  23. if self.count == 0:
  24. return False
  25. self.headIndex = (self.headIndex + 1) % self.capacity
  26. self.count -= 1
  27. return True
  28. def Front(self) -> int:
  29. """
  30. Get the front item from the queue.
  31. """
  32. if self.count == 0:
  33. return -1
  34. return self.queue[self.headIndex]
  35. def Rear(self) -> int:
  36. """
  37. Get the last item from the queue.
  38. """
  39. # empty queue
  40. if self.count == 0:
  41. return -1
  42. return self.queue[(self.headIndex + self.count - 1) % self.capacity]
  43. def isEmpty(self) -> bool:
  44. """
  45. Checks whether the circular queue is empty or not.
  46. """
  47. return self.count == 0
  48. def isFull(self) -> bool:
  49. """
  50. Checks whether the circular queue is full or not.
  51. """
  52. return self.count == self.capacity

数据流中的移动平均值

  1. class MovingAverage:
  2. def __init__(self, size: int):
  3. self.maxSize=size
  4. self.window=[]
  5. def next(self, val: int) -> float:
  6. if len(self.window)==self.maxSize:
  7. self.window.pop(0)
  8. self.window.append(val)
  9. return sum(self.window)/len(self.window)

钥匙和房间

  1. class Solution:
  2. def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
  3. length=len(rooms)
  4. queue=collections.deque()
  5. visited=[False for i in range(length)]
  6. queue.append(0)
  7. visited[0]=True
  8. while queue:
  9. size=len(queue)
  10. for _ in range(size):
  11. keys=rooms[queue.popleft()]
  12. for key in keys:
  13. if not visited[key]:
  14. visited[key]=True
  15. queue.append(key)
  16. return sum(visited)==length

BFS

广度优先搜索(BFS)的一个常见应用是找出从根结点到目标结点的最短路径。
BFS模板:通常使用队列 + 不重复元素的hashmap或者visited

  1. def BFS(root, target):
  2. if not root:return xx
  3. queue=collections.deque()
  4. visited = [[False for i in range(n)] for j in range(m)]
  5. step=0
  6. queue.append(root)
  7. while queue:
  8. step+=1
  9. size=len(queue)
  10. for i in range(size):
  11. curr=queue.popleft()
  12. visited[curr]=True
  13. if curr==target:return step
  14. for next in neibours:
  15. if next not in visited:
  16. queue.append(next)
  17. vivisted[next]=True

两种情况不需要使用visited

  • 树:确定没有循环
  • 希望多次访问同一个节点

    岛屿数量:基础BFS

    1. class Solution:
    2. def numIslands(self, grid: List[List[str]]) -> int:
    3. if not grid or not grid[0]:return 0
    4. m,n=len(grid),len(grid[0])
    5. directions=[(1,0),(-1,0),(0,1),(0,-1)]
    6. def bfs(r,c):
    7. queue=collections.deque()
    8. queue.append((r,c))
    9. while queue:
    10. size=len(queue)
    11. for _ in range(size):
    12. currR,currC=queue.popleft()
    13. if currR<0 or currR>=m or currC<0 or currC>=n:continue
    14. if grid[currR][currC]=='0':continue
    15. grid[currR][currC]='0'
    16. for d in directions:
    17. queue.append((currR+d[0],currC+d[1]))
    18. count=0
    19. for i in range(m):
    20. for j in range(n):
    21. if grid[i][j]=='1':
    22. count+=1
    23. bfs(i,j)
    24. return count

    打开转盘锁:字符串处理邻居

    1. class Solution:
    2. def openLock(self, deadends: List[str], target: str) -> int:
    3. def neibours_process(curr):
    4. result=[]
    5. for i in range(4):
    6. result.append(curr[:i]+str((int(curr[i])+1)%10)+curr[i+1:])
    7. result.append(curr[:i]+str((int(curr[i])-1)%10)+curr[i+1:])
    8. return result
    9. def bfs(root,target):
    10. queue=collections.deque()
    11. queue.append(root)
    12. visited=set()
    13. step=0
    14. while queue:
    15. size=len(queue)
    16. for _ in range(size):
    17. curr=queue.popleft()
    18. if curr in visited:continue
    19. if curr in deadends:continue
    20. if curr==target:return step
    21. visited.add(curr)
    22. neibours=neibours_process(curr)
    23. for next in neibours:
    24. queue.append(next)
    25. step+=1
    26. result=bfs("0000",target)
    27. return result if isinstance(result,int) else -1

    完全平方数:简单剪枝

    1. class Solution:
    2. def numSquares(self, n: int) -> int:
    3. if n==1:return 1
    4. def bfs(n):
    5. queue=collections.deque()
    6. queue.append(n)
    7. count=0
    8. while queue:
    9. size=len(queue)
    10. for _ in range(size):
    11. number=queue.popleft()
    12. temp=int(sqrt(number))
    13. if number==temp**2:return count+1
    14. for i in range(temp,0,-1):
    15. queue.append(number-i**2)
    16. count+=1
    17. count=bfs(n)
    18. return count if isinstance(count,int) else -1

    墙与门:多源点同步BFS

    1. class Solution:
    2. def wallsAndGates(self, rooms: List[List[int]]) -> None:
    3. if not rooms or not rooms[0]:return rooms
    4. m,n=len(rooms),len(rooms[0])
    5. queue=collections.deque()
    6. visited=[[False for i in range(n)]for j in range(m)]
    7. directions=[(1,0),(-1,0),(0,1),(0,-1)]
    8. step=0
    9. for i in range(m):
    10. for j in range(n):
    11. if rooms[i][j]==0:
    12. queue.append((i,j))
    13. while queue:
    14. size=len(queue)
    15. for _ in range(size):
    16. currR,currC=queue.popleft()
    17. if currR<0 or currR>=m or currC<0 or currC>=n:continue
    18. if visited[currR][currC]:continue
    19. if rooms[currR][currC]==-1:continue
    20. if rooms[currR][currC]>step:rooms[currR][currC]=step
    21. visited[currR][currC]=True
    22. for d in directions:
    23. queue.append((currR+d[0],currC+d[1]))
    24. step+=1
    25. return rooms

    01矩阵:多源BFS模板

    多源BFS模板,注意添加进元素的时候避免重复:

  • 扫描向队列添加源点的时候,就设置visited[i][j]=True

  • 访问的时候,只对可行的元素继续搜索
  • 添加元素进队列的时候,同步设置visited[i][j]=True

    • 为了避免重复添加相同元素:就是需要添加的时候同步设置已经访问过
    • 如果像之前那样等下一层再去设置,就晚了(有可能已经添加过了)

      1. class Solution:
      2. def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
      3. if not matrix or not matrix[0]:return matrix
      4. m,n=len(matrix),len(matrix[0])
      5. queue=collections.deque()
      6. visited=[[False for i in range(n)] for j in range(m)]
      7. directions=[(1,0),(-1,0),(0,1),(0,-1)]
      8. step=0
      9. for i in range(m):
      10. for j in range(n):
      11. if matrix[i][j]==0:
      12. queue.append((i,j))
      13. visited[i][j]=True
      14. while queue:
      15. size=len(queue)
      16. for _ in range(size):
      17. currR,currC=queue.popleft()
      18. matrix[currR][currC]=step
      19. for d in directions:
      20. nextR,nextC=currR+d[0],currC+d[1]
      21. if 0<=nextR<m and 0<=nextC<n and not visited[nextR][nextC] and matrix[nextR][nextC]!=0:
      22. queue.append((nextR,nextC))
      23. visited[nextR][nextC]=True
      24. step+=1
      25. return matrix

总结

  1. Python的队列 ```python queue=collections.deque()

queue.append(element) queue.popleft()

size=len(queue) ```

  1. 整体来看 BFS 算法思想就是层次遍历
  2. 注意是否需要visited 和 如何生成 neighbors