127. Word Ladder - BFS

้€™้กŒๆ˜ฏ่ฆๆ‰พๅ‡บ start ๆ–‡ๅญ—ๆฏๆฌกๆ›ไธ€ๅ€‹ๅญ—็š„็‹€ๆณไธ‹, ้€™ๅญ—ๆœ‰ๅœจ wordlist,

ไธฆไธ”่ƒฝๅพžstart string ๆ›ๅญ—่ตฐๅˆฐ end string, ๆ›ๆœ€ๅฐ‘็š„ๆ•ธ็›ฎ

idea:

็„กๅ‘ๅœ–ไธญๅ…ฉๅ€‹้ ‚้ปžไน‹้–“็š„ๆœ€็Ÿญ่ทฏๅพ‘็š„้•ทๅบฆ๏ผŒๅฏไปฅ้€š้Ž BFS ้ๆญทๅพ—ๅˆฐ

็‚บไป€้บผBFSๅพ—ๅˆฐ็š„่ทฏๅพ‘ๆœ€็Ÿญ๏ผŸๅฏไปฅๆŠŠ่ตท้ปžๅ’Œ็ต‚้ปžๆ‰€ๅœจ็š„่ทฏๅพ‘ๆ‹‰็›ดไพ†็œ‹๏ผŒๅ…ฉ้ปžไน‹้–“็ทšๆฎตๆœ€็Ÿญ๏ผ›

ๅทฒ็Ÿฅ็›ฎๆจ™้ ‚้ปž็š„ๆƒ…ๆณไธ‹๏ผŒๅฏไปฅๅˆ†ๅˆฅๅพž่ตท้ปžๅ’Œ็›ฎๆจ™้ ‚้ปž๏ผˆ็ต‚้ปž๏ผ‰ๅŸท่กŒ BFS๏ผŒ็›ดๅˆฐ้ๆญท็š„้ƒจๅˆ†ๆœ‰ไบค้›†๏ผŒ้€™ๆ˜ฏ BFS ็š„ๆ€ๆƒณใ€‚

ๆœ‰ๆฒ’ๆœ‰ๅœจ wordlist ๅ…ง, ็”จ hashset ๅˆคๆ–ท contains

ๆญค้กŒๅฏไปฅ็”จ้›™BFS, ็›ฎๅ‰ๅ…ˆ็”จๅ–ฎBFS

https://leetcode.com/problems/word-ladder/discuss/40704/Java-Solution-using-BFS-with-explanation

main idea:

time: O(26ร—wordLen), qsize is too small, ignore?

space: O(26ร—wordLen)

  1. Set put wordList

  2. Q.offer(begin)

  3. BFS, step = 1

  4. replace each char to test set, if set contains endWord, return step+1. else offer Q, remove newword from set

  5. step++

  6. end return 0

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> set = new HashSet<>(wordList);
        if (set.size() == 0 || !set.contains(endWord)) {
            return 0;
        }
        set.remove(beginWord);
        
        Queue<String> q = new LinkedList<>();
        q.offer(beginWord);
        
        int step = 1;
        while (!q.isEmpty()) {
            int qSize = q.size();
            for (int i = 0; i < qSize; i++) { //BFSๅ›บๅฎšๅฏซๆณ•
                String cur = q.poll();
                for (int j = 0; j < cur.length(); j++) {
                    for (char c = 'a'; c <= 'z'; c++) { // ไธ€ๅ€‹ไธ€ๅ€‹ๆ›ๅญ—
                        char[] charArray = cur.toCharArray();
                        charArray[j] = c;
                        String newWord = String.valueOf(charArray);
                        if (set.contains(newWord)) { // ๆฏ”ๅฐๆ˜ฏๅฆๅญ˜ๅœจ
                            if (newWord.equals(endWord)) { // ๆ‰พๅˆฐ endword ๅ›žๅ‚ณ
                                return step + 1;
                            }
                            q.offer(newWord); // ๅ…ถไป–็‹€ๆณ ็นผ็บŒ่ท‘
                            set.remove(newWord); // ็งปๆŽ‰ๆ‰พๅˆฐ้Ž็š„ๅญ—
                        }

                    }
                }
            }
            step++;
        }
        return 0;
    }
}

ๆณจๆ„้€™ๆฎต

char[] charArray = cur.toCharArray(); // ่ฆ้€™ๆ™‚ๅพŒๅ–ๅ‡บ
for (char c = 'a'; c <= 'z'; c++) {
    char[] charArray = cur.toCharArray();
    charArray[j] = c;
    String newWord = String.valueOf(charArray);
    if (set.contains(newWord)) {
        if (newWord.equals(endWord)) {
            return step + 1;
        }
        q.offer(newWord);
        set.remove(newWord);
    }

}

ๅฆ‚ๆžœcharArrayๅœจๆœ€ๅค–้ขๅฐฑๅ–ๅ‡บไพ†ไบ†, ๅ› ็‚บ arrayไธๆ˜ฏimmutable, ็œŸ็š„ๆœƒ่ขซๆ”นๆŽ‰๏ผ

ไธ‹้ข้€™ไพ‹ๅญ,็ฌฌไธ€ๅ€‹ๅญ—ๆฏ่ท‘ๅฎŒๅพŒ, ็›ดๆŽฅ่ฎŠๆœ€ๅพŒ็š„ z ไบ†, ไธๆ˜ฏๅŽŸๆœฌ็š„ๅ€ผไบ†

ไฝ†ๅฆ‚ๆžœๆฏๆฌก้ƒฝๅพž้ ญๅพžcur่ฃก้ข่ฝ‰ๅ‡บไพ†, string cur ้‚„ๆ˜ฏๅŽŸๆœฌ็š„ๆจฃๅญ

ๅƒ้€™ๆจฃ็š„ๅฏซๆณ•, ๆœ€ๅพŒ้‚„่ฆๅšๆขๅพฉ

ๆ‰€ไปฅ็ต่ซ–๏ผš

่ฆๅœจ้€™่ฃกๅ†ๅ–ๅ‡บ

็ต‚ๆญขๆขไปถ็งปๅˆฐ poll ไน‹ๅพŒ

this is better, and as the same with leetcode 433

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        if (wordList == null || wordList.size() == 0) return 0;
        // use bfs, change word to try to meet wordlist
        HashSet<String> set = new HashSet<>(wordList);
        set.remove(beginWord);
        
        Queue<String> queue = new LinkedList<>();
        queue.offer(beginWord);
        int step = 1;
        
        while (!queue.isEmpty()) {
            int qSize = queue.size();
            for (int q = 0; q < qSize; q++) {
                String cur = queue.poll();
                 if (cur.equals(endWord)) return step; // terminator, if reach endWord
                
                for (int j = 0; j < cur.length(); j++) {
                    for (char c = 'a'; c <= 'z'; c++) { // ไธ€ๅ€‹ไธ€ๅ€‹ๆ›ๅญ—
                        char[] charArray = cur.toCharArray();
                        charArray[j] = c;
                        String newWord = String.valueOf(charArray);
                        if (set.contains(newWord)) { // ๆฏ”ๅฐๆ˜ฏๅฆๅญ˜ๅœจ
                            queue.offer(newWord); // ๅ…ถไป–็‹€ๆณ ็นผ็บŒ่ท‘
                            set.remove(newWord); // ็งปๆŽ‰ๆ‰พๅˆฐ้Ž็š„ๅญ—
                        }

                    }
                }
            }
            step++;
        }
        return 0;
    }
}

็‚บไป€้บผๆœ‰ไบ›้กŒ่งฃๆœƒ้œ€่ฆ visited set? ๆˆ‘้€™ๅ€‹ไธ้œ€่ฆ๏ผŸ

ๅ› ็‚บๆˆ‘็š„ไฝœๆณ•ๅœจๆœ‰ๅฐๆ‡‰ๆ™‚ๆœ‰ๅฐ wordset ๅš remove newword, ๆ‰€ไปฅไธ้œ€่ฆๅคšไธ€ๅ€‹ visited set ไพ†ๆชขๆŸฅ

newest version

T: O(26*M^2) , M: word_len , N wordList_size, M^2 because new String also needs M

constructing a new string (String.valueOf(cAry)) inside the loop is 
O(M) because it involves creating a new character array and copying 
M characters into it

S: O(N), set size
class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> set = new HashSet<>(wordList);
        if (!set.contains(endWord)) { // there is a edge case
            return 0;
        }
        Queue<String> queue = new LinkedList<>();
        queue.offer(beginWord);
        int steps = 1; // beginWord is already 1
        
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int q = 0; q < size; q++) {
                String cur = queue.poll();
                if (endWord.equals(cur)) {
                    return steps;
                }
                for (int i = 0; i < cur.length(); i++) {
                    for (char ch = 'a'; ch <= 'z'; ch++) {
                        char cha[] = cur.toCharArray();      
                        cha[i] = ch;
                        String newStr = new String(cha);
                        if (set.contains(newStr)) {
                            queue.offer(newStr);
                            set.remove(newStr); //remember to remove 
                        }
                    }
                }
                
            }
            steps++;
        }
        return 0; // cant find endWord from beginWord's transform
    }
}

/*
do BFS
hit for each char to replace with 26 chars 
if hit wordList put to queue

termial case is equal endWord


*/

key is here

for (int i = 0; i < cur.length(); i++) {
    for (char ch = 'a'; ch <= 'z'; ch++) {
        char cha[] = cur.toCharArray();

and if we don't remove word from set, it will case inf loop,

when doing changes, ok, we geneare dog,

and add to queue, after this it generate hot...

hot generate dog again, and there is still dog in Set -> inf loop!!

Last updated