Word Ladder

描述

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:

  • Only one letter can be changed at a time
  • Each intermediate word must exist in the dictionary
    For example, Given:
  1. start = "hit"
  2. end = "cog"
  3. dict = ["hot","dot","dog","lot","log"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", return its length 5.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.

    分析

求最短路径,用广搜。

单队列

  1. // Word Ladder
  2. // 时间复杂度O(n),空间复杂度O(n)
  3. struct state_t {
  4. string word;
  5. int level;
  6. state_t() { word = ""; level = 0; }
  7. state_t(const string& word, int level) {
  8. this->word = word;
  9. this->level = level;
  10. }
  11. bool operator==(const state_t &other) const {
  12. return this->word == other.word;
  13. }
  14. };
  15. namespace std {
  16. template<> struct hash<state_t> {
  17. public:
  18. size_t operator()(const state_t& s) const {
  19. return str_hash(s.word);
  20. }
  21. private:
  22. std::hash<std::string> str_hash;
  23. };
  24. }
  25. class Solution {
  26. public:
  27. int ladderLength(const string& start, const string &end,
  28. const unordered_set<string> &dict) {
  29. queue<state_t> q;
  30. unordered_set<state_t> visited; // 判重
  31. auto state_is_valid = [&](const state_t& s) {
  32. return dict.find(s.word) != dict.end() || s.word == end;
  33. };
  34. auto state_is_target = [&](const state_t &s) {return s.word == end; };
  35. auto state_extend = [&](const state_t &s) {
  36. unordered_set<state_t> result;
  37. for (size_t i = 0; i < s.word.size(); ++i) {
  38. state_t new_state(s.word, s.level + 1);
  39. for (char c = 'a'; c <= 'z'; c++) {
  40. // 防止同字母替换
  41. if (c == new_state.word[i]) continue;
  42. swap(c, new_state.word[i]);
  43. if (state_is_valid(new_state) &&
  44. visited.find(new_state) == visited.end()) {
  45. result.insert(new_state);
  46. }
  47. swap(c, new_state.word[i]); // 恢复该单词
  48. }
  49. }
  50. return result;
  51. };
  52. state_t start_state(start, 0);
  53. q.push(start_state);
  54. visited.insert(start_state);
  55. while (!q.empty()) {
  56. // 千万不能用 const auto&,pop() 会删除元素,
  57. // 引用就变成了悬空引用
  58. const auto state = q.front();
  59. q.pop();
  60. if (state_is_target(state)) {
  61. return state.level + 1;
  62. }
  63. const auto& new_states = state_extend(state);
  64. for (const auto& new_state : new_states) {
  65. q.push(new_state);
  66. visited.insert(new_state);
  67. }
  68. }
  69. return 0;
  70. }
  71. };

双队列

  1. // Word Ladder
  2. // 时间复杂度O(n),空间复杂度O(n)
  3. class Solution {
  4. public:
  5. int ladderLength(const string& start, const string &end,
  6. const unordered_set<string> &dict) {
  7. queue<string> current, next; // 当前层,下一层
  8. unordered_set<string> visited; // 判重
  9. int level = -1; // 层次
  10. auto state_is_valid = [&](const string& s) {
  11. return dict.find(s) != dict.end() || s == end;
  12. };
  13. auto state_is_target = [&](const string &s) {return s == end;};
  14. auto state_extend = [&](const string &s) {
  15. unordered_set<string> result;
  16. for (size_t i = 0; i < s.size(); ++i) {
  17. string new_word(s);
  18. for (char c = 'a'; c <= 'z'; c++) {
  19. // 防止同字母替换
  20. if (c == new_word[i]) continue;
  21. swap(c, new_word[i]);
  22. if (state_is_valid(new_word) &&
  23. visited.find(new_word) == visited.end()) {
  24. result.insert(new_word);
  25. }
  26. swap(c, new_word[i]); // 恢复该单词
  27. }
  28. }
  29. return result;
  30. };
  31. current.push(start);
  32. visited.insert(start);
  33. while (!current.empty()) {
  34. ++level;
  35. while (!current.empty()) {
  36. // 千万不能用 const auto&,pop() 会删除元素,
  37. // 引用就变成了悬空引用
  38. const auto state = current.front();
  39. current.pop();
  40. if (state_is_target(state)) {
  41. return level + 1;
  42. }
  43. const auto& new_states = state_extend(state);
  44. for (const auto& new_state : new_states) {
  45. next.push(new_state);
  46. visited.insert(new_state);
  47. }
  48. }
  49. swap(next, current);
  50. }
  51. return 0;
  52. }
  53. };

相关题目

原文: https://soulmachine.gitbooks.io/algorithm-essentials/content/cpp/bfs/word-ladder.html