• 最小操作数


    题目详情

    给了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",有以下两种可能:

    1. "hit" -> "hot" ->  "dot" ->  "dog" -> "cog";
    2. "hit" ->  "hot" ->  "lot" ->  "log"  ->"cog"。
    答题说明
    1. A和B相同的情况下不需要做转换,此时直接返回空集;
    2. 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 ) );
    	}
    
    }
    

      

  • 相关阅读:
    09、AppBarControl
    15、ScrollViewerSample
    11、DataBinding
    18、Compression
    关于创建oracle dblink 过程的几点心得吧
    教你如何玩转DK血
    DK需要知道的事
    Displaying Dynamic KML with ASP.NET
    WLK:裁缝/附魔350450速冲攻略
    WLK狂暴,防御战士的一点心得.
  • 原文地址:https://www.cnblogs.com/i2u9/p/min_op_numbers.html
Copyright © 2020-2023  润新知