LeetCode 127 Word Ladder java (看某位大神的解法做出来的)

问题重述:

Given two words (beginWord and endWord), and a dictionary’s word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
Only one letter can be changed at a time Each intermediate word must exist in the word list
For example,
Given:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,”dot”,”dog”,”lot”,”log”]
As one shortest transformation is “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
return its length 5.
Note:
Return 0 if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
Subscribe to see which companies asked this question

代码如下:其实代码啦,思想啦都是那位大神的,他在LeetCode上给过源码啦,我只是说一下我对他算法的理解

import java.util.HashSet;
import java.util.Set;

import org.junit.Test;
/**
 * 基本思想:模拟
 */
public class Solution {
    public int ladderLength(String beginWord, String endWord, Set<String> wordList) {
        Set<String> start = new HashSet<>();
        Set<String> end = new HashSet<>();

        start.add(beginWord);
        end.add(endWord);
        return solve(start, end, wordList, 1);
    }
    public int solve(Set<String> start,Set<String> end,Set<String> wordList,int step){
        if(start.isEmpty()){
            return 0;
        }
        if(start.size()>end.size()){
            return solve(end,start,wordList,step);
        }
        wordList.removeAll(start);

        Set<String> next = new HashSet<String>();
        for(String s : start){
            char[] chs = s.toCharArray();
            for (int i = 0; i < chs.length; i++) {
                for (int j = 'a'; j <='z'; j++) {
                    char t = chs[i];
                    chs[i]=(char) j;
                    String temp = new String(chs);
                    if(end.contains(temp)){
                        return step+1;
                    }
                    if(wordList.contains(temp)){
                        next.add(temp);
                    }
                    chs[i] = t;
                }
            }
        }
        return solve(next, end, wordList, step+1);
    }
    @Test
    public void test(){
        Set<String> set = new HashSet<>();
        set.add("hot");
        set.add("dog");
        set.add("dot");
        ladderLength("hot","dog",set);
    }
}

创建两个集合,一个开始集合、一个结束集合,由开始集合向结束集合靠近,或者由结束集合向开始集合靠近,这个想法有点像图论中求点到点最短路的算法,都是集合向集合逼近,只不过这个算法有点盲目基本是靠穷举举出来的。

for(String s : start){
    char[] chs = s.toCharArray();
    for (int i = 0; i < chs.length; i++) {
        for (int j = 'a'; j <='z'; j++) {
            char t = chs[i];
            chs[i]=(char) j;
            String temp = new String(chs);
            if(end.contains(temp)){
                return step+1;
            }
            if(wordList.contains(temp)){
                next.add(temp);
            }
            chs[i] = t;
        }
    }
}

这段代码就是穷举的代码,将开始字符集中的每一个字符串中的每一个字符都替换一次,然后判断结果集合或者字符集合里是否包含更改后的字符,如果包含,添加到next集合中,next集合是下一次要查询的开始集。
需要注意的是,更改字符后记得把更改后的字符改回来(就像搜索算法中的染色,有些染色必须再染回去,不然会发生错误,我算法敲得少,所以经常忘记这一点)

此外原作者进行了一个简化:

wordList.removeAll(start);

将查询过的字符串从字符表中删除,这一步确保算法不做重复的工作,极大得改进了算法性能

还有一个优化就是:

if(start.size()>end.size()){
    return solve(end,start,wordList,step);
}

这一步确保三重循环是循环的较小的那个集合,可以带来一定的优化

你可能感兴趣的:(leetcode)