C++ 什么';该算法获取所有单词阶梯的时间复杂度是多少?
字梯C++ 什么';该算法获取所有单词阶梯的时间复杂度是多少?,c++,algorithm,big-o,depth-first-search,breadth-first-search,C++,Algorithm,Big O,Depth First Search,Breadth First Search,字梯 给定两个单词(开始和结束)和一本字典,全部查找 从开始到结束的最短转换序列, 这样:一次只能更改一个字母,每个中间词必须存在于词典中 例如,给定:start=“命中”end=“重心”dict=[“热点”、“点”、“狗”、“批次”、“日志”]返回 [ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ] 注意:所有单词的长度都相同。所有单词只包含小写字母 我个人认为,该算法的时间复杂度取决于 输入
给定两个单词(开始和结束)和一本字典,
全部查找 从开始到结束的最短转换序列,
这样:
一次只能更改一个字母,每个中间词必须存在于词典中
例如,
给定:start=“命中”
end=“重心”
dict=[“热点”、“点”、“狗”、“批次”、“日志”]
返回
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
注意:所有单词的长度都相同。
所有单词只包含小写字母
我个人认为,该算法的时间复杂度取决于 输入(开始、结束、记录)不能像时间复杂度那样写出= O(?)。
谢谢你。紧时间复杂性= O(len*N*(26^(N/2)),len是给定起始字符串的长度(或 结束字符串),n是DICT的元素数(假设C++) 无序_集由has集实现)。请查看下面的详细信息 此解决方案的想法:BFS(Map)+DFS。[C++]
#include <vector>
#include <unordered_map>
#include <deque>
#include <string>
using namespace std;
struct Node {
string val;
int level;
vector<Node *> prevs;
Node (string val, int level): val(val), level(level) {};
};
class Solution {
public:
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
vector<vector<string>> list;
// Input validation.
if (start.compare(end) == 0) {
vector<string> subList = {start, end};
list.push_back(subList);
return list;
}
deque<string> queue;
unordered_map<string, Node *> map;
queue.push_back(start);
Node *start_node = new Node(start, 0);
map.emplace(start, start_node);
while (!queue.empty()) {
// Dequeue.
string curr_string = queue.front();
queue.pop_front();
Node *curr_node = map.find(curr_string)->second;
int curr_level = curr_node->level;
int len = curr_string.length();
if (curr_string.compare(end) == 0) {
// Find the end.
vector<string> subList;
subList.push_back(curr_node->val);
getAllPathes(curr_node, list, subList);
return list;
}
// Iterate all children.
for (int i = 0; i < len; i ++) {
char curr_original_char = curr_string[i];
// Have a try.
for (char c = 'a'; c <= 'z'; c ++) {
if (c == curr_original_char) continue;
curr_string[i] = c;
if (dict.find(curr_string) != dict.end()) {
if (map.find(curr_string) == map.end()) {
// The new string has not been visited.
Node *child = new Node(curr_string, curr_level + 1);
// Add the parents of the current into prevs.
child->prevs.push_back(curr_node);
// Enqueue.
queue.push_back(curr_string);
map.emplace(curr_string, child);
} else {
// The new string has been visited.
Node *child = map.find(curr_string)->second;
if (child->level == curr_level + 1) {
child->prevs.push_back(curr_node);
}
}
}
}
// Roll back.
curr_string[i] = curr_original_char;
}
}
return list;
}
void getAllPathes(Node *end, vector<vector<string>> &list, vector<string> &subList) {
// Base case.
if (end == NULL) {
// Has been get to the top level, no topper one.
vector<string> one_rest(subList);
list.push_back(one_rest);
return;
}
vector<Node *> prevs = end->prevs;
if (prevs.size() > 0) {
for (vector<Node *>::iterator it = prevs.begin();
it != prevs.end(); it ++) {
// Have a try.
subList.insert(subList.begin(), (*it)->val);
// Do recursion.
getAllPathes((*it), list, subList);
// Roll back.
subList.erase(subList.begin());
}
} else {
// Do recursion.
getAllPathes(NULL, list, subList);
}
}
};
#包括
#包括
#包括
#包括
使用名称空间std;
结构节点{
字符串val;
智力水平;
向量预测;
节点(字符串val,int-level):val(val),level(level){};
};
类解决方案{
公众:
矢量查找加法器(字符串开始、字符串结束、无序集合和dict){
向量表;
//输入验证。
如果(开始比较(结束)==0){
向量子列表={start,end};
列表。推回(子列表);
退货清单;
}
排队;
无序地图;
队列。推回(启动);
Node*start\u Node=新节点(start,0);
映射放置(开始,开始节点);
而(!queue.empty()){
//下队。
字符串curr_string=queue.front();
queue.pop_front();
Node*curr\u Node=map.find(curr\u字符串)->秒;
int curr\u level=当前节点->级别;
int len=curr_string.length();
如果(当前字符串比较(结束)==0){
//找到终点。
向量子列表;
子列表。推回(当前节点->值);
GetAllPaths(当前节点、列表、子列表);
退货清单;
}
//迭代所有子项。
对于(int i=0;isecond;
如果(子->级别==当前级别+1){
子节点->上推后(当前节点);
}
}
}
}
//滚回去。
当前字符串[i]=当前原始字符;
}
}
退货清单;
}
void getAllPaths(节点*结束、向量和列表、向量和子列表){
//基本情况。
if(end==NULL){
//已经达到了最高水平,没有一流的。
向量1_rest(子列表);
列表。推回(剩余一个);
返回;
}
向量prevs=结束->上一个;
如果(上一个大小()>0){
for(vector::iterator it=prevs.begin();
it!=prevs.end();it++){
//试试看。
插入(subList.begin(),(*it)->val);
//执行递归。
getAllPaths((*it)、列表、子列表);
//滚回去。
subList.erase(subList.begin());
}
}否则{
//执行递归。
GetAllPaths(空、列表、子列表);
}
}
};
拆分
让我们将复杂性分为三部分:
n
为给定单词的长度,设n
为字典中的单词数。还假定字典已排序
1.部分
然后你可以在O(n)中找到下一个单词⋅ 26⋅ log(N))=O(N log N)
步骤
单词中可以更改的字符n
每个字符可能的更改26
查找字典中是否存在该单词log(N)
[“ab”、“bb”、“bc”、“cc”、…]。
这个例子需要26个转换,我认为你可以构建最坏情况下的输入,需要26n-1个转换 但这取决于词典中的单词。因此最坏的情况是
N
,即使用词典中的所有单词
3.部分
存在多少不同的序列
每次你在序列中寻找下一个单词时,都有可能找到26个不同的下一步。但只适用于最短序列长度的前半部分,因为如果你切换开始和结束单词,这也适用。因此最多可能有O(26N/2)
不同的序列,只要最短序列的最坏情况长度是O(N)
总结
查找序列中的下一个转换O(n log n)
每个序列的变换O(N)
不同的序列O(26N/2)
O(26N/2n log N)
通知
- 只有当您的字典可以包含任何字符序列作为“单词”时,这一点才成立。如果您只允许存在于真实语言中的单词,您可以使用统计数据来证明一个更好的方法