[US Giants] 八. Search & Recurison

Word Search

Given a 2D board and a word, find if the word exists in the grid.

The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once.

Given board =

[
  "ABCE",
  "SFCS",
  "ADEE"
]

word = "ABCCED", -> returns true,
word = "SEE", -> returns true,
word = "ABCB", -> returns false.

思路:遍歷找到單詞的第一個字母,然後開始四個方向上dfs。但是這題有一點要注意就是題沒有要求每一個字母cell只能用一次,因此要將當前這串裏訪問過的字母用'#'表示,當整個dfs完再將mark爲'#'的字母復原。

復原字母的原因是例如'CCB',在找到C爲第一個字母開始遍歷以後,經過遞歸發現沒有合適的結果,復原這裏面標記過的字母,返回false,然後再遍歷後面的字母,直到遇到C,以C爲第一個字母開始遍歷,因爲這個C會在向上走的時候取到C,所以如果之前不復原,這時候這個C的位置是'#',導致結果錯誤。

public class Solution {
    public boolean exist(char[][] board, String word) {
        if(board==null || board.length==0){
            return false;
        }  
        if(word.length()==0){
            return true;
        }        
        for(int i=0;i<board.length;i++){
            for(int j=0;j<board[0].length;j++){
                if(board[i][j]==word.charAt(0)){ 
                    if(find(board,i,j,word,0)){
                        return true;
                    }
                }
            }
        }
        return false;        
    }
    
    private boolean find(char[][] board,int i,int j,String word,int pos){
        if(pos==word.length()){
           return true; 
        }
        if(!isValid(board,i,j,word) || board[i][j]!=word.charAt(pos)){
            return false;
        }
               
        board[i][j]='#';
        boolean result=find(board,i-1,j,word,pos+1)
                     ||find(board,i+1,j,word,pos+1)
                     ||find(board,i,j-1,word,pos+1)
                     ||find(board,i,j+1,word,pos+1);
        board[i][j]=word.charAt(pos);
        return result;      
    } 
    
    
    private boolean isValid(char[][] board,int x,int y,String word){
        if(x<0 || x>=board.length){
            return false;
        }
        if(y<0 || y>=board[0].length){
            return false;
        }
        return true;
    }
}

Word Ladder

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
Example

Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

public class Solution {
    /**
      * @param start, a string
      * @param end, a string
      * @param dict, a set of string
      * @return an integer
      */
    public int ladderLength(String start, String end, Set<String> dict) {
        if(dict==null || dict.size()==0){
            return 0;
        }
        if(start.equals(end)){
            return 1;
        }
        dict.add(start);
        dict.add(end);
        
        Queue<String> queue=new LinkedList<>();
        Set<String> set=new HashSet<>();
        
        queue.offer(start);
        set.add(start);
        
        int length=1;
        while(!queue.isEmpty()){
            length++;                           //由題目的例子知,算上start和end,雖然結果是5,但中間轉換4次
            int size=queue.size();              //只要queue不爲空,就length++,如果當前的就是end,返回此時的length
            for(int i=0;i<size;i++){
                String cur=queue.poll();        //對於當前的cur,拿到dict裏相應的變形詞list
                for(String nextWord:getNextWords(cur,dict)){  
                    if(set.contains(nextWord)){ //要找最短路徑,一定是這個詞用過就不會再用了
                        continue;               //因爲如果有第二次用,幹嘛不直接用第一次時候的結果
                    }
                    if(nextWord.equals(end)){
                        return length;
                    }
                    queue.offer(nextWord);
                    set.add(nextWord);
                }
            }
        }
        return length;
    }
                                               //找到word在dict裏存在的每一個變形詞,並且只能一個字符改變
    private ArrayList<String> getNextWords(String word,Set<String> dict){
        ArrayList<String> list=new ArrayList<>();
        for(char c='a';c<='z';c++){
            for(int i=0;i<word.length();i++){
                if(c==word.charAt(i)){
                    continue;
                }
                String nextWord=replaceWord(word,i,c);
                if(dict.contains(nextWord)){
                    list.add(nextWord);
                }
            }
        }
        return list;
    } 
    
    private String replaceWord(String word,int i,char c){
        char[] chars=word.toCharArray();
        chars[i]=c;
        return new String(chars);
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章