首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >广度优先算法

广度优先算法

原创
作者头像
半月无霜
发布2025-01-31 11:52:51
发布2025-01-31 11:52:51
4190
举报
文章被收录于专栏:半月无霜半月无霜

一、前言

在上一篇文章中,我使用到了深度优先算法,它是一种处理点线点之间问题的一种思路。

简单的来说,深度优先算法可以简单理解为从一个方向上死磕,如果这个方向上行不通,那就回到最近的一个分叉点,走另一个方向进行尝试解决。其这种深入死磕的方式,被我们称为深度优先算法。

但往往在图解问题上,深度优先算法并不是最优解决的算法方案。这个时候,我们就要考虑使用广度优先算法了。

广度优先算法,顾名思义,它与深度优先算法成两个对立面,它会充分的往每个方向尝试,从而找到最优解。

二、广度优先

我们可以看下这道比较简单的题目,作为我们学习广度优先算法的入门算法题

出自力扣的104题,链接如下

104. 二叉树的最大深度 - 力扣(LeetCode)

image-20250129110030903
image-20250129110030903

可以给大家几分钟思考一下,要破题很简单,但如果使用广度优先算法如何进行解题

我这边直接给大家代码了

代码语言:javascript
复制

简单讲解一下,我将每一层的节点元素放到一个list集合里,通过遍历将它们的子节点们重新生成一个list集合。

通过判断这个集合是否有值来确定深度是否加1,这种解法保证了每一层节点的雨露均沾,一个都不落下。

直到再也没有子节点了,也就能正确确认二叉树的深度了

当然,这道题目也可以用深度优先算法来解决,大家也可以试试看

三、单词接龙

现在你已经掌握了广度优先算法的精髓,现在来试试这道稍微有点点难度的算法题,它出自力扣算法题第127题,链接如下

127. 单词接龙 - 力扣(LeetCode)

image-20250129121822050
image-20250129121822050

在本算法题中,非常抽象的是单词的概念,单词在list集合中,相邻的元素只有一个字母进行改变

那么广度优先算法如何解决这个问题?是不是没有思路与想法

我上面说过,广度优先算法是解决点线点问题的一个解题思路。那么本题只有单词,那不行,我们需要抽象出一个点线点的概念。

从上面相邻元素只有一个字母改变的题目特性来看,这当中的点就是单词里面的字母,这个线连接的就是相邻单词改变的两个字母

有了这个思路,就可以尝试使用广度优先算法来进行解题了,大家也可以试试看

代码语言:javascript
复制
package com.banmoon.arithmetic.leetcode;
​
import java.util.*;
​
/**
 * <a href="https://leetcode.cn/problems/word-ladder/?envType=problem-list-v2&envId=breadth-first-search">单词接龙</a>
 */
public class Question127 {
​
    public static void main(String[] args) {
        Question127 question127 = new Question127();
        List<String> wordList = Arrays.asList("hot", "dot", "dog", "lot", "log", "cog");
        int i = question127.ladderLength("hit", "cog", wordList);
        System.out.println(i);
    }
​
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        // 第 1 步:先将 wordList 放到哈希表里,便于判断某个单词是否在 wordList 里
        Set<String> wordSet = new HashSet<>(wordList);
        if (wordSet.size() == 0 || !wordSet.contains(endWord)) {
            return 0;
        }
        wordSet.remove(beginWord);
​
        // 第 2 步:图的广度优先遍历,必须使用队列和表示是否访问过的 visited 哈希表
        Queue<String> queue = new LinkedList<>();
        queue.offer(beginWord);
        Set<String> visited = new HashSet<>();
        visited.add(beginWord);
​
        // 第 3 步:开始广度优先遍历,包含起点,因此初始化的时候步数为 1
        int step = 1;
        while (!queue.isEmpty()) {
            int currentSize = queue.size();
            for (int i = 0; i < currentSize; i++) {
                // 依次遍历当前队列中的单词
                String currentWord = queue.poll();
                // 如果 currentWord 能够修改 1 个字符与 endWord 相同,则返回 step + 1
                if (changeWordEveryOneLetter(currentWord, endWord, queue, visited, wordSet)) {
                    return step + 1;
                }
            }
            step++;
        }
        return 0;
    }
​
    private boolean changeWordEveryOneLetter(String currentWord, String endWord,
                                             Queue<String> queue, Set<String> visited, Set<String> wordSet) {
        char[] charArray = currentWord.toCharArray();
        for (int i = 0; i < endWord.length(); i++) {
            // 先保存,然后恢复
            char originChar = charArray[i];
            for (char k = 'a'; k <= 'z'; k++) {
                if (k == originChar) {
                    continue;
                }
                charArray[i] = k;
                String nextWord = String.valueOf(charArray);
                if (wordSet.contains(nextWord)) {
                    if (nextWord.equals(endWord)) {
                        return true;
                    }
                    if (!visited.contains(nextWord)) {
                        queue.add(nextWord);
                        // 注意:添加到队列以后,必须马上标记为已经访问
                        visited.add(nextWord);
                    }
                }
            }
            // 恢复
            charArray[i] = originChar;
        }
        return false;
    }
​
}
image-20250131114326079
image-20250131114326079

上面代码可以看这段题解,比我讲得更加详细

127. 单词接龙 - 力扣(LeetCode)

这道题目虽然难度上升了不少,但核心依旧是图算法的题解,难点在于如何将单词抽象出图的点线点概念。

只要有了这一层概念,就能使用广度优先的思路进行解题了

四、最后

好了,经过这两道算法题,相信你已经对广度优先算法有了一定的了解,相信遇到类似的问题,也能有对应的思路,剩下的就是具体的代码实现了。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、广度优先
  • 三、单词接龙
  • 四、最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档