From a37563a3e7fb011ded21cb64378455d06253fc6e Mon Sep 17 00:00:00 2001 From: ShusenTang Date: Mon, 8 Jul 2019 23:25:30 +0800 Subject: [PATCH] add 127 --- solutions/127. Word Ladder.md | 122 ++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 solutions/127. Word Ladder.md diff --git a/solutions/127. Word Ladder.md b/solutions/127. Word Ladder.md new file mode 100644 index 0000000..6d099e2 --- /dev/null +++ b/solutions/127. Word Ladder.md @@ -0,0 +1,122 @@ +# [127. Word Ladder](https://leetcode.com/problems/word-ladder/) +# 思路 +词句阶梯: 给了我们一个单词字典,里面有一系列很相似的单词,然后给了一个起始单词和一个结束单词,每次变换只能改变一个单词,并且中间过程的单词都必须是单词字典中的单词,让我们求出最短的变化序列的长度。 +要求最短路径长度,首先应该想到BFS。类似迷宫里面的最短路求法,迷宫每个点有上下左右四个方向可以走,而这里有26个字母,就是二十六个方向可以走,本质上没有区别。 + +另外由于需要频繁判断某个单词是否在字典中,所以我们用hashSet记录词典(代码中的`wordSet`)以快速进行判断。 + +## 思路一 +采用递归的BFS。首先我们用一个词语数组`beginWords`来记录开始的词语,初始化为一个元素`beginWord`,此外类似走迷宫的题目我们还需要一个`visited`来记录当前词语是否被访问过,这里我们用hashSet来定义`visited`。递归出口是`beginWords`为空。 + + +## 思路二、思路一改进 +仔细分析我们可以发现了个hashSet`wordSet`和`visited`其实在功能上是有冗余的: 如果我们每访问一次`wordSet`里的词然后就把它从`wordSet`中去掉,这样不就不需要`visited`了吗?亲测会比思路一快很多。 + +## 思路三 +思路二的非递归版本。此时就不需要`beginWords`了而需要一个队列。 + +# C++ +## 思路一 +``` C++ +class Solution { +private: + int BFS(vectorbeginWords, unordered_set&wordSet, + unordered_set&visited, string &endWord){ + vectornext_beginWords; + string word; + for(int i = 0; i < beginWords.size(); i++){ + for(int j = 0; j < endWord.size(); j++){ + word = beginWords[i]; + if(word == endWord) return 1; + for(char k = 'a'; k <= 'z'; k++){ + word[j] = k; + if(!wordSet.count(word) || visited.count(word)) continue; + + visited.insert(word); + next_beginWords.push_back(word); + } + } + } + if(next_beginWords.empty()) return 0; // 递归出口 + return BFS(next_beginWords, wordSet, visited, endWord) + 1; + } + +public: + int ladderLength(string beginWord, string endWord, vector& wordList) { + unordered_setwordSet(wordList.begin(), wordList.end()); + unordered_setvisited{beginWord}; + if(wordSet.count(endWord) != 1) return 0; + vectorbeginWords{beginWord}; + return BFS(beginWords, wordSet, visited, endWord); + } +}; +``` + +## 思路二 +``` C++ +class Solution { +private: + int BFS(vectorbeginWords, unordered_set&wordSet, string &endWord){ + vectornext_beginWords; + string word; + for(int i = 0; i < beginWords.size(); i++){ + for(int j = 0; j < endWord.size(); j++){ + word = beginWords[i]; + if(word == endWord) return 1; + char tmp_c = word[j]; + for(char k = 'a'; k <= 'z'; k++){ + word[j] = k; + // tmp_c == k即新旧单词相同 + if(!wordSet.count(word) || tmp_c == k) continue; + + wordSet.erase(word); + next_beginWords.push_back(word); + } + } + } + if(next_beginWords.empty()) return 0; // 递归出口 + return BFS(next_beginWords, wordSet, endWord) + 1; + } + +public: + int ladderLength(string beginWord, string endWord, vector& wordList) { + unordered_setwordSet(wordList.begin(), wordList.end()); + if(wordSet.count(endWord) != 1) return 0; + vectorbeginWords{beginWord}; + return BFS(beginWords, wordSet, endWord); + } +}; +``` + +## 思路三 +``` C++ +class Solution { +public: + int ladderLength(string beginWord, string endWord, vector& wordList) { + unordered_set wordSet(wordList.begin(), wordList.end()); + if (!wordSet.count(endWord)) return 0; + queue q; + q.push(beginWord); + int res = 0; + while (!q.empty()) { + for (int k = q.size(); k > 0; --k) { + string word = q.front(); q.pop(); + if (word == endWord) return res + 1; + for (int i = 0; i < word.size(); ++i) { + string newWord = word; + for (char k = 'a'; k <= 'z'; ++k) { + newWord[i] = k; + if (wordSet.count(newWord) && newWord != word) { + q.push(newWord); + wordSet.erase(newWord); + } + } + } + } + ++res; + } + return 0; + } +}; +``` +