小明思考

          Just a software engineer
          posts - 124, comments - 36, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          字梯游戲

          Posted on 2013-04-18 12:46 小明 閱讀(1524) 評論(0)  編輯  收藏 所屬分類: 數據結構和算法
          問題給定兩個單詞(一個開始,一個結束)和一個字典,找出最短的從開始單詞到結束單詞的變換序列的長度,并滿足:

          1.每次只能變換一個字母
          2.所有的中間單詞必須存在于字典中

          比如:
          輸入:
          start = "hit"
          end = "cog"
          dict = ["hot","dot","dog","lot","log"]

          那么最短的變化序列是"hit" -> "hot" -> "dot" -> "dog" -> "cog",所以返回長度是5。
          注意:
          1. 如果找不到這樣的序列,返回0
          2. 所有單詞的長度都是相同的
          3. 所有單詞都只含有小寫的字母。

          分析:
          這個問題本質是一個圖論中的尋求最短路徑的問題。之前做過一個迷宮尋路的demo,有興趣的可以看看:http://slab.sinaapp.com/pathfinder/

          為了提高效率,把輸入的HashSet轉化成數組來處理,并預先計算好他們相互的關系。下面使用的算法是BFS,在大多數情況下,都是足夠快的。如果要優化,可以使用A*,但是實現的復雜度就會大幅增加。

          代碼如下:
          public class WordLadder {
              
              private boolean canChange(char[] a,char[] b){
                  int diff = 0;
                  int len = a.length;
                  for(int i=0;i<len;++i){
                      if(a[i]!=b[i]){
                          ++diff;
                          if(diff>1){
                              return false;
                          }
                      }
                  }
                  return true;
              }
              
              public int ladderLength(String start, String end, HashSet<String> dict) {
                  Object[] all = new Object[dict.size()+2];
                  int t=0;
                  all[t++]=start.toCharArray();
                  for(String d:dict){
                      all[t++]=d.toCharArray();
                  }
                  all[t++]=end.toCharArray();
                  int size = all.length;
                  boolean[][] matrix = new boolean[size][size];
                  for(int i=0;i<size;++i){
                      char[]si = (char[])all[i];
                      for(int j=i+1;j<size;++j){
                          char[] sj = (char[])all[j];
                          if(canChange(si,sj)){
                              matrix[i][j] = matrix[j][i] = true;  
                          }
                      }
                  }
                  
                  int[] cost = new int[size];
                  for(int i=0;i<size;++i){
                      cost[i] = Integer.MAX_VALUE;
                  }
                  cost[0] = 0;
                  List<Integer> openlist = new ArrayList<Integer>();
                  openlist.add(0);
                  int target = size-1;
                  while(!openlist.isEmpty()){
                      int current = openlist.remove(openlist.size()-1);
                      boolean[] mn = matrix[current];
                      int cc =  cost[current];
                      for(int i=0;i<size;++i){
                          if(mn[i]){
                              if(i==target){ //find
                                  return cc+2;
                              }
                              if(cost[i]>cc+1){
                                  cost[i]=cc+1;
                                  openlist.add(0,i);
                              }
                          }
                      }
                  }
                  return 0;
              }
          }
          主站蜘蛛池模板: 郧西县| 庆阳市| 民县| 阆中市| 安岳县| 双柏县| 安新县| 漾濞| 常宁市| 大理市| 木里| 锡林浩特市| 静宁县| 三江| 玉龙| 六盘水市| 二连浩特市| 通化市| 南靖县| 山西省| 亳州市| 论坛| 长武县| 嘉鱼县| 桐乡市| 健康| 醴陵市| 板桥市| 峨眉山市| 兰溪市| 皋兰县| 淄博市| 武山县| 金寨县| 驻马店市| 新绛县| 铅山县| 蒲江县| 德钦县| 内江市| 全州县|