Cover image for 面试经典150题 P127 单词接龙

面试经典150题 P127 单词接龙

字数 842
阅读
访客

时间轴

时间轴

2025-11-24

init

BFS

题目:

BFS 暴力枚举,这是我最先想出的方法,但是效率很低。

BFS 暴力枚举

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
#include <string>#include <queue>#include <unordered_set>#include <vector>using std::string;using std::unordered_set;using std::vector;using std::queue;class Solution {    private:	bool is_neighbor(string word, string possible_neighbor)	{		int diff_cnt = 0, n = word.size();		if (possible_neighbor.size() != n) {			return false;		}		for (int i = 0; i < n; i++) {			if (word[i] != possible_neighbor[i]) {				diff_cnt++;			}			if (diff_cnt > 1) {				return false;			}		}		return true;	}    public:	int ladderLength(string beginWord, string endWord, vector<string> &wordList)	{		int i, n, level = 1;		queue<string> que;		unordered_set<string> visited;		string curr_word;		que.push(beginWord);		visited.insert(beginWord);		while (!que.empty()) {			n = que.size();			for (i = 0; i < n; i++) {				curr_word = que.front();				que.pop();				if (curr_word == endWord) {					return level + 1;				}				for (auto &possible_neighbor : wordList) {					if (!visited.count(possible_neighbor) &&					    is_neighbor(curr_word, possible_neighbor)) {						que.push(possible_neighbor);						visited.insert(possible_neighbor);					}				}			}			level++;		}		return 0;	}};

BFS+虚拟节点优化建图

官方题解:我们先给每一个单词标号,即给每个单词分配一个 id。创建一个由单词 word 到 id 对应的映射 wordId,并将 beginWord 与 wordList 中所有的单词都加入这个映射中。之后我们检查 endWord 是否在该映射内,若不存在,则输入无解。我们可以使用哈希表实现上面的映射关系。

然后我们需要建图,依据朴素的思路,我们可以枚举每一对单词的组合,判断它们是否恰好相差一个字符,以判断这两个单词对应的节点是否能够相连。但是这样效率太低,我们可以优化建图。

具体地,我们可以创建虚拟节点。对于单词 hit,我们创建三个虚拟节点 it、ht、hi*,并让 hit 向这三个虚拟节点分别连一条边即可。如果一个单词能够转化为 hit,那么该单词必然会连接到这三个虚拟节点之一。对于每一个单词,我们枚举它连接到的虚拟节点,把该单词对应的 id 与这些虚拟节点对应的 id 相连即可。

最后我们将起点加入队列开始广度优先搜索,当搜索到终点时,我们就找到了最短路径的长度。注意因为添加了虚拟节点,所以我们得到的距离为实际最短路径长度的两倍。同时我们并未计算起点对答案的贡献,所以我们应当返回距离的一半再加一的结果。

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
class Solution {public:    unordered_map<string, int> wordId;    vector<vector<int>> edge;    int nodeNum = 0;    void addWord(string& word) {        if (!wordId.count(word)) {            wordId[word] = nodeNum++;            edge.emplace_back();        }    }    void addEdge(string& word) {        addWord(word);        int id1 = wordId[word];        for (char& it : word) {            char tmp = it;            it = '*';            addWord(word);            int id2 = wordId[word];            edge[id1].push_back(id2);            edge[id2].push_back(id1);            it = tmp;        }    }    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {        for (string& word : wordList) {            addEdge(word);        }        addEdge(beginWord);        if (!wordId.count(endWord)) {            return 0;        }        vector<int> dis(nodeNum, INT_MAX);        int beginId = wordId[beginWord], endId = wordId[endWord];        dis[beginId] = 0;        queue<int> que;        que.push(beginId);        while (!que.empty()) {            int x = que.front();            que.pop();            if (x == endId) {                return dis[endId] / 2 + 1;            }            for (int& it : edge[x]) {                if (dis[it] == INT_MAX) {                    dis[it] = dis[x] + 1;                    que.push(it);                }            }        }        return 0;    }};
评论加载中…