2021-10-13:单词接龙。字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:序列中第一个单词是 beginWord 。序列中最后一个单词是 endWord 。每次转换只能改变一个字母。转换过程中的中间单词必须是字典 wordList 中的单词。给你两个单词 beginWord 和 endWord 和一个字典 wordList ,找到从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0。力扣127。

福大大 答案2021-10-13:

宽度优先遍历。找邻居。

代码用golang编写。代码如下:

package main

import "fmt"

func main() {
    beginWord := "hit"
    endWord := "cog"
    wordList := []string{"hot", "dot", "dog", "lot", "log", "cog"}
    ret := ladderLength1(beginWord, endWord, wordList)
    fmt.Println(ret)

}

// start,出发的单词
// to, 目标单位
// list, 列表
// to 一定属于list
// start未必
// 返回变幻的最短路径长度
func ladderLength1(start string, to string, list0 []string) int {
    list0 = append(list0, start)

    // key : 列表中的单词,每一个单词都会有记录!
    // value : key这个单词,有哪些邻居!
    nexts := getNexts(list0)
    // abc  出发     abc  -> abc  0
    //
    // bbc  1
    distanceMap := make(map[string]int)
    distanceMap[start] = 1
    set := make(map[string]struct{})
    set[start] = struct{}{}
    queue := make([]string, 0)
    queue = append(queue, start)
    for len(queue) > 0 {
        cur := queue[0]
        queue = queue[1:]
        distance := distanceMap[cur]
        for _, next := range nexts[cur] {
            if next == to {
                return distance + 1
            }
            if _, ok := set[next]; !ok {
                set[next] = struct{}{}
                queue = append(queue, next)
                distanceMap[next] = distance + 1
            }
        }

    }
    return 0
}

func getNexts(words []string) map[string][]string {
    dict := make(map[string]struct{})
    for _, word := range words {
        dict[word] = struct{}{}
    }
    nexts := make(map[string][]string)
    for i := 0; i < len(words); i++ {
        nexts[words[i]] = getNext(words[i], dict)
    }
    return nexts
}

// 应该根据具体数据状况决定用什么来找邻居
// 1)如果字符串长度比较短,字符串数量比较多,以下方法适合
// 2)如果字符串长度比较长,字符串数量比较少,以下方法不适合
func getNext(word string, dict map[string]struct{}) []string {
    res := make([]string, 0)
    chs := []byte(word)
    for i := 0; i < len(chs); i++ {
        for cur := 'a'; cur <= 'z'; cur++ {
            if chs[i] != byte(cur) {
                tmp := chs[i]
                chs[i] = byte(cur)
                if _, ok := dict[fmt.Sprintf("%s", chs)]; ok {
                    res = append(res, fmt.Sprintf("%s", chs))
                }
                chs[i] = tmp
            }
        }
    }
    return res
}

func ladderLength2(beginWord string, endWord string, wordList []string) int {
    dict := make(map[string]struct{})
    for _, word := range wordList {
        dict[word] = struct{}{}
    }
    if _, ok := dict[endWord]; !ok {
        return 0
    }
    startSet := make(map[string]struct{})
    endSet := make(map[string]struct{})
    visit := make(map[string]struct{})
    startSet[beginWord] = struct{}{}
    endSet[endWord] = struct{}{}
    for len0 := 2; len(startSet) > 0; len0++ {
        // startSet是较小的,endSet是较大的
        nextSet := make(map[string]struct{})
        for w, _ := range startSet {
            // w -> a(nextSet)
            // a b c
            // 0
            //   1
            //     2
            for j := 0; j < len(w); j++ {
                ch := []byte(w)
                for c := 'a'; c <= 'z'; c++ {
                    if byte(c) != w[j] {
                        ch[j] = byte(c)
                        next := fmt.Sprintf("%c", ch)
                        if _, ok := endSet[next]; ok {
                            return len0
                        }
                        _, ok1 := dict[next]
                        _, ok2 := visit[next]
                        if ok1 && !ok2 {
                            nextSet[next] = struct{}{}
                            visit[next] = struct{}{}
                        }
                    }
                }
            }
        }
        // startSet(小) -> nextSet(某个大小)   和 endSet大小来比
        //startSet = (nextSet.size() < endSet.size()) ? nextSet : endSet;
        startSet = endSet
        if len(nextSet) < len(endSet) {
            startSet = nextSet
        }
        //endSet = (startSet == nextSet) ? endSet : nextSet;
        b := len(startSet) == len(endSet)
        if b {
            for ss, _ := range startSet {
                if _, ok := endSet[ss]; ok {

                } else {
                    b = false
                    break
                }
            }
        }
        if !b {
            endSet = nextSet
        }
    }
    return 0
}

执行结果如下: 图片


左神java代码