原题地址

既然是求最短路径,可以考虑动归或广搜。这道题对字典直接进行动归是不现实的,因为字典里的单词非常多。只能选择广搜了。

思路也非常直观,从start或end开始,不断加入所有可到达的单词,直到最终到达另一端。本质上广度优先遍历图。

需要注意的是,拓展下一个单词时不能对字典进行枚举,因为字典里的单词太多。幸好单词本身都不长,所以直接枚举单词所有可能的变形,看看在dict中出现没有。

当然还不止这些,上面的做法仍然会超时,需要添加剪枝策略:

1. 如果某个单词在以前遍历过了,那么以后都不用再考虑,因为之后遍历到的路径一定不是最短的

2. 在广搜法拓展下一轮单词时,注意去重

此外还需要注意的是,不能把每个单词到start或end的路径都保存下来,那样内存会爆掉。所以要压缩保存结果,通常的做法是用一个map保存当前单词下一步是什么单词。例如next[word] = {next_word1, next_word2, next_word3...}。最后从next[start]开始再次使用广度优先搜索法构造出所有解。

算法不难,但是编码非常容易出错,所以总体上还是挺难的。最后运行时间640ms,还是有挺大优化空间的。

代码写的有些啰嗦,DFS不一定要用队列(我还是用了队列),这道题用unordered_set更好,不需要用额外的数据结构去重了。

代码:

 bool adjacentp(string &a, string &b) {
for (int i = a.length() - , d = ; i >= ; i--) {
d += a[i] != b[i] ? : ;
if (d > )
return false;
}
return true;
} vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict) {
map<string, set<string> > next;
unordered_set<string> covered; // 当前已经访问过的单词
queue<string> que;
bool found = false; // 是否已经找到 next[end] = set<string>();
covered.insert(end);
que.push(end);
while (!que.empty() && !found) {
unordered_set<string> rset;
queue<string> rque; while (!que.empty()) {
string curr = que.front();
que.pop(); if (adjacentp(curr, start)) {
found = true;
next[start].insert(curr);
continue;
} for (int i = curr.length() - ; i >= ; i--) {
for (int j = ; j < ; j++) {
string prev = curr;
prev[i] = 'a' + j;
// 如果prev之前没有被访问过,且字典里有这个单词
if (covered.find(prev) == covered.end() && dict.find(prev) != dict.end()) {
next[prev].insert(curr);
// 如果在DFS的本轮拓展中还没有访问过该节点,则加入下一轮的拓展节点中
if (rset.find(prev) == rset.end()) {
rset.insert(prev);
rque.push(prev);
}
}
}
}
}
que = rque;
for (auto w : rset) {
covered.insert(w);
}
} queue<vector<string> > laddersQue;
vector<vector<string> > ladders;
laddersQue.push(vector<string>(, start));
while (!laddersQue.empty()) {
vector<string> ladder = laddersQue.front();
laddersQue.pop();
if (ladder.back() == end)
ladders.push_back(ladder);
else {
for (auto s : next[ladder.back()]) {
vector<string> newLadder = ladder;
newLadder.push_back(s);
laddersQue.push(newLadder);
}
}
} return ladders;
}

Leetcode#126 Word Ladder II的更多相关文章

  1. Java for LeetCode 126 Word Ladder II 【HARD】

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...

  2. [LeetCode] 126. Word Ladder II 词语阶梯 II

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  3. LeetCode 126. Word Ladder II 单词接龙 II(C++/Java)

    题目: Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transfo ...

  4. [LeetCode] 126. Word Ladder II 词语阶梯之二

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  5. leetcode 126. Word Ladder II ----- java

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...

  6. leetcode@ [126] Word Ladder II (BFS + 层次遍历 + DFS)

    https://leetcode.com/problems/word-ladder-ii/ Given two words (beginWord and endWord), and a diction ...

  7. leetcode 127. Word Ladder、126. Word Ladder II

    127. Word Ladder 这道题使用bfs来解决,每次将满足要求的变换单词加入队列中. wordSet用来记录当前词典中的单词,做一个单词变换生成一个新单词,都需要判断这个单词是否在词典中,不 ...

  8. 126. Word Ladder II(hard)

    126. Word Ladder II 题目 Given two words (beginWord and endWord), and a dictionary's word list, find a ...

  9. [Leetcode Week5]Word Ladder II

    Word Ladder II 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/word-ladder-ii/description/ Descripti ...

随机推荐

  1. STL之vector

    参考资料:      1.codeproject      2.csdn      3.cplusplus

  2. informix dbaccess 常用执行方式及常见技巧

    假设: A.数据库servername: testserver B.数据库名:testdb C.SQL脚本文件: sqlfile.sql create table test_table(c1 inte ...

  3. js获取html5 audio 音频时长方法

    <audio src="我的好兄弟.mp3" controls="controls"  id="audio" style=" ...

  4. c++中回调函数和函数指针的使用

    #include "stdafx.h" #include <iostream> //#include <string> using namespace st ...

  5. 5款Mac极速下载工具推荐和下载

    最近几年用到下载工具的情况其实很少了,比如几年前我们可能经常用下载工具下载视频.音乐.图书等资源,但今天的我们更多的在线看视频.在线听音乐了,偶尔用到下载的时候直接用浏览器自带的下载工具也完全够用了, ...

  6. C#设计模式(11)——外观模式(Facade Pattern)(转)

    一.引言 在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然而为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ...

  7. Javascript高级编程学习笔记(12)—— 引用类型(1)Object类型

    前面的文章中我们知道JS中的值分为两种类型 基础类型的值和引用类型的值 基础类型的值我已经大概介绍了一下,今天开始后面几天我会为大家介绍一下引用类型的值 Object类型 对象是引用类型的值的实例,在 ...

  8. SQLSERVER文件组误脱机后如何联机

    场景:在学习文件组的恢复过程中,通过 ALTER DATABASE TEST MODIFY FILE(NAME = SUBF,OFFLINE) 把文件组给弄脱机了.这时却发现脱机之前忘记备份了. 这时 ...

  9. python基础学习19----socket网络编程

    网络通信三要素 ip地址:InetAddress 网络中设备的标识,不易记忆,可用主机名(计算机的标识号) 端口号:用于标识进程的逻辑地址,不同进程的标识(正在运行的软件的标识号) 传输协议:通讯的规 ...

  10. 960CSS框架,之前有用过 了解下框架基本原理

    http://blog.sina.com.cn/s/blog_8173443e010160b8.html CSS框架已经出现很长时间了,关于这些框架的用处也被我们讨论了很多遍了.有人说,CSS框架不够 ...