最小操作数
题目详情
给了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"。
答题说明
- A和B相同的情况下不需要做转换,此时直接返回空集;
- main函数是为方便你在提交代码之前进行在线编译测试,可不完成。
思路:分析问题的本质, 单词连线即可得到一个无向 无权图,问题即是求图中两个节点的所有最短路径。因为最短路径 很容易想到 广度优先,或者 Dijstra算法。
① 分层搜索
② 逐层计算路径
源码如下:
package hero; import java.util.*; public class Minopnum { public Vector<Vector<String>> findLadders(String start, String end, Set<String> dict) { Vector<Vector<String>> retval = new Vector<Vector<String>>(); // check arguments if( start.equals(end) ){ return retval; } else if( start == null || end == null ){ return null ; } int ab = similar(start, end) , L = start.length() ; if( ab == 1){ Vector<String> path = new Vector<String>(); path.add(start); path.add(end); retval.add(path) ; return retval; } else if( ab == 3){ return retval; } if( dict == null || dict.isEmpty() ){ return retval ; } // main process Vector<HashSet<String>> tiers = new Vector<HashSet<String>>() ; HashSet<String> ftier = new HashSet<String>(); ftier.add(start); tiers.add(ftier); HashMap<String,HashSet<String>> prenodes = new HashMap<String,HashSet<String>>(); HashSet<String> unused = new HashSet<String>(); for(String word : dict){ if(word != null && word.length() == L ){ unused.add(word); } } if( unused.contains(start)){ unused.remove(start); } if( unused.contains(end)){ unused.remove(end); } boolean exists = false ; HashSet<String> ends = findlikes(end, unused); while( ! unused.isEmpty() ){ HashSet<String> nexttier = new HashSet<String>(); HashSet<String> deadwords = new HashSet<String>(); boolean endtier = false; HashSet<String> last = tiers.get( tiers.size() - 1 ); for(String word: last ){ HashSet<String> wto = findlikes(word, unused); if( wto.isEmpty() ){ deadwords.add(word); } else { nexttier.addAll(wto); for(String tword: wto){ if( ! prenodes.containsKey(tword) ){ prenodes.put(tword, new HashSet<String>()); } prenodes.get(tword).add(word); } if( endtier == false ){ HashSet<String> t = setsame(ends,wto); if( ! t.isEmpty() ){ endtier = true; exists = true; } } } } if( nexttier.isEmpty() ){ break; } for(String w: deadwords){ last.remove(w); } for(String w: nexttier){ unused.remove(w); } if( endtier ){ tiers.add( setsame(ends,nexttier ) ); break; } else { tiers.add(nexttier); } } // end each tier if( ! exists ){ // after find all nodes return retval; } prenodes.put(end, tiers.get( tiers.size() - 1)); HashSet<String> etier = new HashSet<String>(); etier.add(end); tiers.add(etier); HashMap<String,Vector<Vector<String>>> pathes = new HashMap<String,Vector<Vector<String>>>(); Vector<String> startpath = new Vector<String>(); startpath.add(start); retval.add(startpath); pathes.put(start, retval); for(int i=1,Lt=tiers.size();i<Lt;i++){ for(String w : tiers.get(i) ){ pathes.put(w, new Vector<Vector<String>>() ); for(String p : prenodes.get(w) ){ for(Vector<String> path : pathes.get(p) ){ @SuppressWarnings("unchecked") Vector<String> newpath = (Vector<String>) path.clone(); newpath.add(w); pathes.get(w).add(newpath); } } } } return pathes.get(end) ; } public static HashSet<String> findlikes(String a, Set<String> words){ HashSet<String> likes = new HashSet<String>() ; for(String s : words ){ if( similar(a, s) == 1 ){ likes.add(s); } } return likes ; } public static int similar(String a, String b){ assert a != null && b != null; if( a.equals(b) ){ return 0 ; } else if( a.length() != b.length() ){ return 3; } boolean diff = false; for(int i=0,L=a.length();i<L;i++){ if( a.charAt(i) != b.charAt(i) ){ if( diff ){ return 2; } diff = true; } } return 1 ; } public static HashSet<String> setsame(HashSet<String> a, HashSet<String> b){ HashSet<String> c = new HashSet<String>(); for(String w : a){ if( b.contains(w)){ c.add(w); } } return c; } public static void main(String[] args) { /* * hot dog [cog, dog, dot, hog, hop, hot, pot, tot] */ String[] d = {"cog", "dog", "dot", "hog", "hop", "hot", "pot", "tot"} ; Set<String> dict = new HashSet<String>(); for(int i=0;i<d.length;i++){ dict.add(d[i]); } Minopnum t = new Minopnum(); System.out.println( t.findLadders("hot", "dog", dict ) ); } }
posted on 2013-10-29 23:29 Simple Love 阅读(1148) 评论(0) 编辑 收藏 举报