首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【庞果英雄会】最小操作数

  • 25-03-02 17:21
  • 2810
  • 6720
blog.csdn.net

给了A、B两个单词和一个单词集合Dict,每个的长度都相同。我们希望通过若干次操作把单词A变成单词B,每次操作可以改变单词中的一个字母,同时,新产生的单词必须是在给定的单词集合Dict中。求所有行得通步数最少的修改方法。    

举个例子如下: 

Given:    A = "hit"    B = "cog"    

Dict = ["hot","dot","dog","lot","log"] 

Return  [    ["hit","hot","dot","dog","cog"],    ["hit","hot","lot","log","cog"]  ]     

即把字符串A = "hit"转变成字符串B = "cog",有以下两种可能: 

"hit" -> "hot" ->  "dot" ->  "dog" -> "cog"; 

"hit" ->  "hot" ->  "lot" ->  "log"  ->"cog"。 


我的思路如下:

广度优先方式建立多叉树(类似多叉树)。从开始给的字符开始,从字典中找相差一个字母的所有集合,都为开始字符的孩子节点,并将这些节点放到一个列表list中。然后对列表list中的每一个节点N,继续找相差一个字母的所有集合(不包含已经在树上,且深度低于当前处理层的节点),做为N的孩子节点。这样,以广度优先的方式来建立多叉树。最后遇到了单词B,把这一层处理完,就可以从树上倒推得到变化过程了(可行的变化可能有多个)。

根据例子中所给的字典建立多叉树的过程(先要将字符B加入到字典中):


需要注意的是:

1 树是逐层建立起来的,也就是广度优先,而不是深度优先,例如第3层有dot和lot,先将dot和lot放到树上,再着手建立第4层。所以,需要一个辅助列表来保存每一层的的节点。以便于建立下一层。

2 为了保证树的建立过程中,不会出现倒回头的现象,所以已经添加到树上的节点需要标记,在我的代码中初始化节点的深度为-1,表示还未添加到树上。

3 树的两个分支可能包含同一个孩子节点,例如上面从第4层到第5层。cog节点有两个父节点,所以严格来说,这并不是一个树^_^ 另外,cog在处理dog节点的时候已经添加到树上,但是在处理log节点时,又处理了一次,看似于第2点矛盾,其实不然,因为dog和log是处在同一层的,为了记录所有可行的方案需要这样处理。

4 可以不记录节点的孩子节点情况,但是为了最后回溯结果,每个节点要记录自己的父节点(可能有多个父节点)。

5 回溯就比较简单了,用一个数组模拟栈,从节点B不停地往父节点方向走,记录所有可行路径。


具体还是看代码吧,我下面这个代码在庞果网提交并没有通过,应该还是有考虑不周的地方,恳请读者不吝赐教。

  1. // MinOperationCount.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include
  5. #include
  6. #include
  7. #include
  8. #include
  9. using namespace std;
  10. typedef struct _NODE
  11. {
  12. vector vecParentNode;
  13. int nDeep;
  14. bool isEnd;
  15. }NODE, *PNODE;
  16. bool IsNear(const string & strDest, const string & strSource)
  17. {
  18. int nLenDest = strDest.length();
  19. int nLenSource = strSource.length();
  20. if (nLenSource != nLenDest)
  21. {
  22. return false;
  23. }
  24. int nDiff = 0;
  25. for (int i = 0; i < nLenSource; i++)
  26. {
  27. if (strDest.at(i) != strSource.at(i))
  28. {
  29. nDiff++;
  30. }
  31. }
  32. if (1 == nDiff)
  33. {
  34. return true;
  35. }
  36. return false;
  37. }
  38. bool FindNearString(set &setStrFind, map &mapStrNode, int nDeep)
  39. {
  40. bool bRet = false;
  41. set setStrNext;
  42. set::iterator itSet = setStrFind.begin();
  43. for ( ; itSet != setStrFind.end(); itSet++)
  44. {
  45. map::iterator it = mapStrNode.begin();
  46. for ( ; it != mapStrNode.end(); it++)
  47. {
  48. if ( (-1 == it->second.nDeep || nDeep == it->second.nDeep) &&
  49. IsNear(*itSet, it->first))
  50. {
  51. it->second.nDeep = nDeep;
  52. it->second.vecParentNode.push_back(*itSet);
  53. setStrNext.insert(it->first);
  54. if (it->second.isEnd)
  55. {
  56. bRet = true;
  57. }
  58. }
  59. }
  60. }
  61. setStrFind = setStrNext;
  62. return bRet;
  63. }
  64. void OutputArray(string* arrayPath, int nDeep, vector> &vecResult)
  65. {
  66. vector vecStr;
  67. for (int i = nDeep-1; i >= 0; i--)
  68. {
  69. vecStr.push_back(arrayPath[i]);
  70. }
  71. vecResult.push_back(vecStr);
  72. }
  73. void Recur(string* arrayPath, int i, int nDeep, string &strCur,
  74. map &mapStrNode, vector> &vecResult)
  75. {
  76. arrayPath[i] = strCur;
  77. map::iterator it = mapStrNode.find(strCur);
  78. if (it == mapStrNode.end())
  79. {
  80. OutputArray(arrayPath, nDeep, vecResult);
  81. return;
  82. }
  83. for (int j = 0; j < (int)mapStrNode[strCur].vecParentNode.size(); j++)
  84. {
  85. i++;
  86. Recur(arrayPath, i, nDeep, mapStrNode[strCur].vecParentNode[j], mapStrNode, vecResult);
  87. i--;
  88. }
  89. }
  90. void GetMinPath(string &strBegin, string &strEnd,
  91. set &setDict, vector> &vecResult)
  92. {
  93. if (strBegin == strEnd)
  94. {
  95. return;
  96. }
  97. map mapStrNode;
  98. setDict.insert(strEnd);
  99. set::iterator it = setDict.begin();
  100. for ( ; it != setDict.end(); it++)
  101. {
  102. NODE node = {};
  103. node.nDeep = -1;// -1 代表还没有插入到树上
  104. node.isEnd = (*it == strEnd) ? true : false;
  105. mapStrNode[*it] = node;
  106. }
  107. //广度优先建立多叉树
  108. set setStrFind;
  109. setStrFind.insert(strBegin);
  110. int nDeep = 1;
  111. bool isFind = false;
  112. while (setStrFind.size() != 0 && !isFind)
  113. {
  114. isFind = FindNearString(setStrFind, mapStrNode, nDeep);
  115. nDeep++;
  116. }
  117. if (!isFind)
  118. {
  119. return;
  120. }
  121. string* arrayPath = new string[nDeep];
  122. int i = 0;
  123. Recur(arrayPath, i, nDeep, strEnd, mapStrNode, vecResult);
  124. delete [] arrayPath;
  125. }
  126. class Solution
  127. {
  128. public:
  129. vector> findLadders(string start, string end, set& dict)
  130. {
  131. vector> vecResult;
  132. GetMinPath(start, end, dict, vecResult);
  133. return vecResult;
  134. }
  135. };
  136. int _tmain(int argc, _TCHAR* argv[])
  137. {
  138. string strBegin = "hit";
  139. string strEnd= "cig";
  140. set setDict;
  141. setDict.insert("hot");
  142. setDict.insert("git");
  143. setDict.insert("dot");
  144. setDict.insert("dog");
  145. setDict.insert("lot");
  146. setDict.insert("log");
  147. setDict.insert("cog");
  148. vector> vecResult;
  149. Solution so;
  150. vecResult = so.findLadders(strBegin, strEnd, setDict);
  151. vector>::iterator it = vecResult.begin();
  152. for ( ; it != vecResult.end(); it++)
  153. {
  154. vector::iterator itStr = it->begin();
  155. for ( ; itStr != it->end(); itStr++)
  156. {
  157. cout<<*itStr<<" ";
  158. }
  159. cout<<"\n";
  160. }
  161. return 0;
  162. }

update:

经过特例测试,发现是没有考虑到开始字符串出现在字典中的情况,所以将85行代码:

if (it == mapStrNode.end()) 

修改为:

    if (it == mapStrNode.end() || nDeep == i+1)  即可。


注:本文转载自blog.csdn.net的超然_烟火的文章"http://blog.csdn.net/sunnianzhong/article/details/9326289"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top