2021-09-07:单词接龙 II。按字典 wordList 完成从单词 beginWord 到单词 endWord 转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> ... -> sk 这样的单词序列,并满足:每对相邻的单词之间仅有单个字母不同。转换过程中的每个单词 si(1 <= i <= k)必须是字典 wordList 中的单词。注意,beginWord 不必是字典 wordList 中的单词。sk == endWord,给你两个单词 beginWord 和 endWord ,以及一个字典 wordList 。请你找出并返回所有从 beginWord 到 endWord 的 最短转换序列 ,如果不存在这样的转换序列,返回一个空列表。每个序列都应该以单词列表 [beginWord, s1, s2, ..., sk] 的形式返回。力扣126。

福大大 答案2021-09-07:

递归。遍历找邻居。
时间复杂度:O(kN)和O(26k*k)。

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

package main

import "fmt"

func main() {

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

}

func findLadders(start string, end string, list0 []string) [][]string {
    list0 = append(list0, start)
    nexts := getNexts(&list0)
    distances := getDistances(start, nexts)
    pathList := make([]string, 0)
    res := make([][]string, 0)
    getShortestPaths(start, end, nexts, distances, &pathList, &res)
    return res
}

//
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
}

// word, 在表中,有哪些邻居,把邻居们,生成list返回
func getNext(word string, dict map[string]struct{}) []string {
    res := make([]string, 0)
    chs := []byte(word)
    for cur := byte('a'); cur <= 'z'; cur++ {
        for i := 0; i < len(chs); i++ {
            if chs[i] != cur {
                tmp := chs[i]
                chs[i] = cur
                if _, ok := dict[fmt.Sprintf("%s", chs)]; ok {
                    res = append(res, fmt.Sprintf("%s", chs))
                }
                chs[i] = tmp
            }
        }
    }
    return res
}

// 生成距离表,从start开始,根据邻居表,宽度优先遍历,对于能够遇到的所有字符串,生成(字符串,距离)这条记录,放入距离表中
func getDistances(start string, nexts map[string][]string) map[string]int {

    distances := make(map[string]int)
    distances[start] = 0
    queue := make([]string, 0)
    queue = append(queue, start)
    set := make(map[string]struct{})
    set[start] = struct{}{}
    for len(queue) > 0 {
        //cur := queue[len(queue)-1]
        //queue = queue[0 : len(queue)-1]
        cur := queue[0]
        queue = queue[1:]
        for _, next := range nexts[cur] {
            if _, ok := set[next]; !ok {
                distances[next] = distances[cur] + 1
                queue = append(queue, next)
                set[next] = struct{}{}
            }
        }
    }
    return distances
}

// cur 当前来到的字符串 可变
// to 目标,固定参数
// nexts 每一个字符串的邻居表
// cur 到开头距离5 -> 到开头距离是6的支路 distances距离表
// path : 来到cur之前,深度优先遍历之前的历史是什么
// res : 当遇到cur,把历史,放入res,作为一个结果
func getShortestPaths(cur string, to string, nexts map[string][]string, distances map[string]int, path *[]string, res *[][]string) {
    *path = append(*path, cur)
    if to == cur {
        //res.add(new LinkedList<String>(path));
        pathcopy := make([]string, len(*path))
        copy(pathcopy, *path)
        *res = append(*res, pathcopy)
    } else {
        for _, next := range nexts[cur] {
            if distances[next] == distances[cur]+1 {
                getShortestPaths(next, to, nexts, distances, path, res)
            }
        }
    }
    //path.pollLast();
    *path = (*path)[0 : len(*path)-1]
}

执行结果如下:
在这里插入图片描述


左神java代码