Skip to content

Prepare For Coder Interview – Denny

  • Basic
  • Medium
  • Hard
  • Architect
  • Life

LeetCode: Word Ladder II

Posted on January 22, 2018July 26, 2020 by braindenny

Word Ladder II



Similar Problems:

  • LeetCode: Word Ladder
  • CheatSheet: Leetcode For Code Interview
  • CheatSheet: Common Code Problems & Follow-ups
  • Tag: graph, bfs, backtracking

Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

Only one letter can be changed at a time
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
Return
  [
    ["hit","hot","dot","dog","cog"],
    ["hit","hot","lot","log","cog"]
  ]

Note:

  • Return an empty list if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

UPDATE (2017/1/20):
The wordList parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.

Github: code.dennyzhang.com

Credits To: leetcode.com

Leave me comments, if you have better ways to solve.


  • Solution
// https://code.dennyzhang.com/word-ladder-ii
// Basic Ideas: bfs + backtracking
//
// Figure out the distance from beginWord to endWord
// Also the distance from beginWord to any possible word
//   This can speedup the test
//
// Complexity: Time ? Space ?
func getDistance(beginWord string, endWord string, visited map[string]bool, distances map[string]int) int {
    // check whether endWord is a transformed word
    if _, ok := visited[endWord]; !ok {
        return 0
    }
    queue := []string{beginWord}
    level := 1
    distances[beginWord] = 0
    for len(queue) > 0 {
        l := []string{}
        for _, word := range queue {
            bytes := []byte(word)
            for i, ch := range bytes {
                for ch2:='a'; ch2<='z'; ch2++ {
                    // backtracking
                    bytes[i] = byte(ch2)
                    word2 := string(bytes)
                    if word2 != word {
                        // word exists, and not visited
                        if _, ok := visited[word2]; ok && !visited[word2] {
                            l = append(l, word2)
                            // mark node as visited
                            visited[word2] = true
                            // update distance: only the first update would be right
                            if _, ok := distances[word2]; !ok {
                                distances[word2] = level
                            }
                            // update the target node
                            if word2 == endWord {
                                return level+1
                            }
                        }
                    }
                    bytes[i] = ch
                }
            }
        }
        queue = l
        level++
    }
    return 0
}

func dfs(combination []string, endWord string, visited map[string]bool, distances map[string]int, res *[][]string) {
    if combination[len(combination)-1] == endWord {
        // get a candidate
        combination2 := make([]string, len(combination))
        copy(combination2, combination)
        *res = append(*res, combination2)
    } else {
        // explore
        word := combination[len(combination)-1]
        bytes := []byte(word)
        for i, ch := range word {
            for ch2:='a'; ch2<='z'; ch2++ {
                bytes[i] = byte(ch2)
                word2 := string(bytes)
                if word2 != word {
                    if _, ok := visited[word2]; ok && !visited[word2] && distances[word2] == distances[word]+1 {
                        combination = append(combination, word2)
                        visited[word2] = true
                        dfs(combination, endWord, visited, distances, res)
                        // backtracking
                        visited[word2] = false
                        combination = combination[0:len(combination)-1]
                    }
                }
                // change it back: only one character can be changed.
                bytes[i] = byte(ch)
            }
        }
    }
}

func findLadders(beginWord string, endWord string, wordList []string) [][]string {
    if beginWord == endWord {
        return [][]string{[]string{beginWord}}
    }

    visited := map[string]bool{}
    for _, word := range wordList {
        visited[word] = false
    }
    distances := map[string]int{}
    // find distance via BFS
    dis := getDistance(beginWord, endWord, visited, distances)
    if dis == 0 {
        return [][]string{}
    }
    for k, _ := range visited {
        visited[k] = false
    }
    res := [][]string{}
    // backtracking to get all result via dfs
    dfs([]string{beginWord}, endWord, visited, distances, &res)
    return res
}
linkedin
github
slack

Post Views: 9
Posted in HardTagged #backtracking, #bfs, #classic, #graph, #string, redo

Post navigation

LeetCode: Word Ladder
LintCode: Longest Repeating Substring

Leave a Reply Cancel reply

Your email address will not be published.

Tags

#array #backtracking #bfs #binarytree #bitmanipulation #blog #classic #codetemplate #combination #dfs #dynamicprogramming #game #graph #greedy #heap #inspiring #interval #linkedlist #manydetails #math #palindrome #recursive #slidingwindow #stack #string #subarray #trie #twopointer #twosum binarysearch editdistance hashmap intervaldp knapsack monotone oodesign presum rectangle redo review rotatelist series sql treetraversal unionfind

Recent Posts

  • a
  • a
  • a
  • a
  • a

Recent Comments

    Archives

    Categories

    • Amusing
    • Basic
    • Easy
    • Hard
    • Life
    • Medium
    • Resource
    • Review
    • Series
    • Uncategorized
    Proudly powered by WordPress | Theme: petals by Aurorum.