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

来源:互联网 发布:知乎 胡佛 罗斯福 编辑:程序博客网 时间:2024/05/19 19:31

问题重述:

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);}

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

0 0