广度优先搜索

广度优先搜索算法(英语:Breadth-First Search,缩写为BFS),是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。 ——维基百科。

实际应用

BFS在求解最短路径或者最短步数上有很多的应用。

对比

深度优先搜索

深度优先搜索用栈(stack)来实现,整个过程可以想象成一个倒立的树形:
1、把根节点压入栈中。
2、每次从栈中弹出一个元素,搜索所有在它下一级的元素,把这些元素压入栈中。并把这个元素记为它下一级元素的前驱。
3、找到所要找的元素时结束程序。
4、如果遍历整个树还没有找到,结束程序。

广度优先搜索

广度优先搜索使用队列(queue)来实现,整个过程也可以看做一个倒立的树形:
1、把根节点放到队列的末尾。
2、每次从队列的头部取出一个元素,查看这个元素所有的下一级元素,把它们放到队列的末尾。并把这个元素记为它下一级元素的前驱。
3、找到所要找的元素时结束程序。
4、如果遍历整个树还没有找到,结束程序。

具体例子

1. 二叉树最小深度(LeetCode-111)

image.png
解法:

  1. var minDepth = function(root) {
  2. if (!root) return 0
  3. const stack = []
  4. // 把root节点压入stack中
  5. stack.push([root, 1])
  6. let depth = 0
  7. while (stack.length) {
  8. // 取出首位
  9. const current = stack.shift()
  10. const currentRoot = current[0]
  11. depth = current[1]
  12. // 如果当前节点没有下一级了,则为最短路径
  13. if (!currentRoot.left && !currentRoot.right) break
  14. if (currentRoot.left) stack.push([currentRoot.left, depth + 1])
  15. if (currentRoot.right) stack.push([currentRoot.right, depth + 1])
  16. }
  17. return depth
  18. };

2. 二叉树的层次遍历2(LeetCode-107)

image.png
解法:

  1. var levelOrderBottom = function(root) {
  2. if(!root) return []
  3. const stack = []
  4. // 结果数组
  5. const ans = []
  6. // 当前深度
  7. let depth = 0
  8. stack.push([root, 1])
  9. while (stack.length) {
  10. const current = stack.shift()
  11. const currentRoot = current[0]
  12. // 如果迭代深度比当前深度大则新增一个数组
  13. if (current[1] > depth) {
  14. ans.unshift([currentRoot.val])
  15. depth = current[1]
  16. } else {
  17. ans[0].push(currentRoot.val)
  18. }
  19. if (currentRoot.left) stack.push([currentRoot.left, depth + 1])
  20. if (currentRoot.right) stack.push([currentRoot.right, depth + 1])
  21. }
  22. return ans
  23. };

3. 二叉树的堂兄弟(LeetCode-993)

image.png
解法:

  1. var isCousins = function(root, x, y) {
  2. if (!root) return true
  3. const stack = []
  4. let activeTree = null, activeDep = 0, ans = true
  5. stack.push([root, 1, null])
  6. while (stack.length) {
  7. const current = stack.shift()
  8. const currentRoot = current[0]
  9. // 如果不在同一层次 直接返回false
  10. if (activeDep && current[1] > activeDep) {
  11. ans = false
  12. break
  13. }
  14. // 匹配节点时
  15. if (currentRoot.val === x || currentRoot.val === y) {
  16. // 第一次匹配进行赋值保存
  17. if (!activeDep) {
  18. activeDep = current[1]
  19. activeTree = current[2]
  20. } else {
  21. // 第二次匹配如果深度不同或者父节点相同 直接返回fals
  22. if (activeDep !== current[1] || activeTree === current[2] ) {
  23. ans = false
  24. }
  25. break
  26. }
  27. }
  28. if (currentRoot.left) stack.push([currentRoot.left, current[1] + 1 , currentRoot])
  29. if (currentRoot.right) stack.push([currentRoot.right, current[1] + 1 , currentRoot])
  30. }
  31. return ans
  32. };