介绍
方法一
这是我的第一种实现方法,时间复杂度很高,没有通过全部的测试用例,具体看代码就可以了
代码
Solution.java
import java.util.ArrayList;
import java.util.List;
class Solution {
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
//这是最后的返回结果
List<List<String>> ans = new ArrayList<List<String>>();
//表示最短的序列长度, 初始值设置为最大
Integer[] le = {Integer.MAX_VALUE};
//la表示其中一个结果集
List<String> la = new ArrayList<String>();
//加入第一个元素
la.add(beginWord);
//定义一个数组变量来随时表示字典中的字是否被使用过
//多给一个元素,保证下面的程序理解起来简单
Boolean[] btest = new Boolean[wordList.size() + 1];
//定义一个循环,遍历wordList,从beginWord开始查找,在列表中查找和beginWork相差一个单词的元素,那就把这个元素加到一个la中
//并将该元素相应的位置设置为false,表示该元素不能再被读取,然后继续循环,
//直到元素与endWord相同,或者是查找完所有的元素,或者是没有元素可以与之匹配,
//如果当前位置已经大于le,则直接进行回溯,进行下一次查找
//如果是与endWord相同,则进行下一次查找,但是不能和上一个的结果集相同 这里要记录le
//如果是查找完所有的元素,则返回空列表就可以了
//如果是没有元素与之匹配,这里应该是进行回溯,在这里可以考虑使用递归进行回溯,否则直接回溯会很麻烦
//优化问题,这里要找的是最短的序列,因此要记录一个最短的数量
//
for(int i=0; i<btest.length; i++) {
btest[i] = true;
}
Integer let = 0;
//goBack(beginWord, endWord, wordList, ans, le, let, la, btest);
for(int i=1;i<wordList.size()+2;i++) {
le[0] = i;
goBack(beginWord, endWord, wordList, ans, le, let, la, btest);
if(ans.size() != 0) {
break;
}
}
//排除掉所有不合适的元素
for(int i=0; i<ans.size();i++){
//因为有初始元素,所以要+2
while(i<ans.size() && ans.get(i).size() > (le[0]+1)) {
ans.remove(i);
}
}
return ans;
}
/**
* 定义一个回溯函数(递归函数)
* 该递归函数应该查找出需要的结果集
*
* 对函数的结构进行说明,其中应该有一个循环,来进行循环的查找
* @param beginWord 开始字符
* @param endWord 结束字符
* @param wordList 字典,所有的中间结果
* @param ans 最终结果
* @param le 表示最短的序列长度, le应该是引用,可以进行修改
* @param let 表示当前是第几个元素,使用引用
* @param la 表示其中一个结果集
* @param btest 表示该元素是否被使用过
*
*/
void goBack(String beginWord, String endWord, List<String> wordList,
List<List<String>> ans, Integer[] le, Integer let, List<String> la, Boolean[] btest) {
//1.首先let自增,判断是否超出了最短序列,超出则直接返回
let++;
if(let>le[0]) {
return;
}
//2.循环开始---
for(int i=0;i<wordList.size(); i++) {
//3.#---从beginWord开始查找,在列表中查找和beginWork相差一个单词的元素,在该元素为true的情况下
//如果找到了这样一个元素{
if(btest[i] && subOne(beginWord,wordList.get(i)) ) {
//4.那就把这个元素加到一个la中
la.add(wordList.get(i));
//5.---btest将该元素相应的位置设置为false,表示该元素不能再被读取
btest[i] = false;
//6.---如果是与endWord相同,则进行回溯,要记录le,//这里(如果le更小,或者相等都可以)
// 然后要将la放到ans中,//表示找到了其中一个结果这里已经找到结果,这里需要返回return
// 返回(return)之前需要做的操作:首先la中加入的元素删除, 然后btest改为true,最后let--
// 也就是认为还没有找到结果,继续进行查找
if(wordList.get(i).equals(endWord)) {
if(let < le[0]) {
le[0] = let;
}
//重新定义一个laa
List<String> laa = new ArrayList(la);
ans.add(laa);
//System.out.println(laa);
la.remove(la.size()-1);//删除最后一个元素
btest[i] = true;
//let[0]--;
//进行查找下一个
return;
}
//7.---这里就是与不endWord相同,表示需要查找下一个元素,将beginWord设置为当前的结果,调用自身递归查询,进行递归即可
String beginWordIn = wordList.get(i);
goBack(beginWordIn, endWord, wordList, ans, le, let, la, btest);
//8.---递归返回了,说明该路径已经查找完毕,必须弹出当前点,找另外一个点替换当前点,这里做弹出当前点的操作就可以
//.---弹出当前点需要做的操作:首先la中加入的元素删除, 然后btest改为true
la.remove(la.size()-1);//删除最后一个元素
btest[i] = true;
//let[0]--; //这里不用减少,因为还是在同函数中
}
//# }
}
//9.循环跳出---如果是没有元素与之匹配,直接进行回溯就可以,
// 因为之前弹出了当前点,所以这里不用重复弹出
// 函数返回之前要减少
//let[0]--;
return;
}
/**
* 判断当前这两个字符串是否相差一个元素,相等的情况不做考虑
* @param one 第一个字符串
* @param two 第二个字符串
* @return
*/
boolean subOne(String one, String two) {
//表示当前有几个元素不同
int sum = 0;
for(int i=0;i<one.length();i++)
{
//如果元素不同,则计数器加一
if(one.charAt(i) != two.charAt(i)) {
sum++;
if(sum > 1) {
break;
}
}
}
//如果只有一个不同,返回true
if(sum ==1 ) {
return true;
}else {
return false;
}
}
}
Test.java
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
Solution s = new Solution();
String beginWord = "hit";
String endWord = "cog";
List<String> wordList = new ArrayList<String>();
String[] a = {"hot","dot","dog","lot","log","cog"};
for(int i=0;i<a.length;i++) {
wordList.add(a[i]);
}
System.out.println(s.findLadders(beginWord, endWord, wordList));
System.out.println(s.subOne("dot", "log"));;
Integer i = new Integer(666666);
fun(i);
System.out.println(i);
}
public static void fun(Integer i) {
i = 1;
}
}
方法二
算法介绍
官方的解答
算法是参考官方的解答,使用的方法是图的广度优先遍历,在遍历的过程中记录路径,因为要找的是所有的最短路径,所以要做一个记录,然后遍历这些路径,看路径的最后一个点是否是终点,当然在前面应该判断,如果字典中没有终点,直接返回空就可以了。
在这个过程中需要注意的问题
注意一下问题
Integer i1 = 200;
Integer i2 = 200;
#结果是false
System.out.println(i1 == i2);
#结果是true
System.out.println(i1.equals(i2));
为什么是这样的,请详细查看java关于Integer的说明,查看Integer的源代码进行理解,在此只给出一个范围。 -128~+127 之间都是true,超出这个范围的是false和true。本人在这里栽了,这种问题是比较难以发现的问题,想多了解请查看文档。
代码
Solution.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
/**
* 此种解决方案是使用广度优先算法
* @author 123
*
*/
class Solution {
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
//这是最后的返回结果
List<List<String>> ans = new ArrayList<List<String>>();
//建立序号和图的序号
//由字符串查找点
Map<String, Integer> sitm = new HashMap<String, Integer>();
//由序号查找字符串
List<String> sitl = new ArrayList<String>();
for(int i=0;i<wordList.size(); i++) {
String temp = wordList.get(i);
//这里判断一下更好,避免有重复的数据
if(!sitm.containsKey(temp)) {
sitm.put(temp, i);
sitl.add(temp);
}
}
//如果终点不在字典中,直接退出
if(!sitm.containsKey(endWord)) {
return ans;
}
//将起点加入
sitm.put(beginWord, wordList.size());
sitl.add(beginWord);
//将图定义和实现出来
//List<List<Integer>>
List<List<Integer>> mapl = new ArrayList<List<Integer>>();//图
for(int i=0;i<sitl.size(); i++) {
List<Integer> temp = new ArrayList<Integer>();
mapl.add(temp);
}
//
for(int i=0;i<sitl.size(); i++) {
for(int j=i+1;j<sitl.size(); j++) {
if(subOne(sitl.get(i), sitl.get(j))){
//建立一条无向边
mapl.get(i).add(j);
mapl.get(j).add(i);
}
}
}
//首先应该定义一个队列
//Queue
Queue<List<Integer>> q = new LinkedList<List<Integer>>();
//定义权重
List<Integer> weight = new ArrayList<Integer>();
for(int i=0;i<sitl.size();i++) {
weight.add(Integer.MAX_VALUE);
}
//将开始节点的权重设置为0
weight.set(weight.size()-1, 0);
//定义result,记录过程路径
List<Integer> result = new ArrayList<Integer>();
result.add(sitm.get(beginWord));
q.add(result);
while(!q.isEmpty()) {
List<Integer> one = q.poll();
//如果最后一个元素是endWord
Integer last = one.get(one.size()-1); //这是路径中的最后一个元素
if(one.size() == 11) {
int sfsf;
sfsf = 1;
}
if(last.equals(sitm.get(endWord))) {
//那么将该路径放入到结果集
List<String> temp = new ArrayList<String>();
for(int i=0;i<one.size(); i++){
temp.add(sitl.get(one.get(i)));
}
ans.add(temp);
}
else {
//否则就查找下一个元素
List<Integer> visit = new ArrayList<Integer>(mapl.get(last));
for(int i=0;i<visit.size();i++) {
Integer temp = visit.get(i);
if(weight.get(temp) >= weight.get(last)+1) {
//更改权重
weight.set(temp, weight.get(last)+1);
List<Integer> temp2 = new ArrayList<Integer>(one);
temp2.add(temp);
//debug
//debug
q.add(temp2);
}
}
}
}
//进行遍历
return ans;
}
/**
* 判断当前这两个字符串是否相差一个元素,相等的情况不做考虑
* @param one 第一个字符串
* @param two 第二个字符串
* @return
*/
boolean subOne(String one, String two) {
//表示当前有几个元素不同
int sum = 0;
for(int i=0;i<one.length();i++)
{
//如果元素不同,则计数器加一
if(one.charAt(i) != two.charAt(i)) {
sum++;
if(sum > 1) {
break;
}
}
}
//如果只有一个不同,返回true
if(sum ==1 ) {
return true;
}else {
return false;
}
}
}
Test.java
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
Solution s = new Solution();
String beginWord = "cet";
String endWord = "ism";
List<String> wordList = new ArrayList<String>();
String[] a = {"kid","tag","pup","ail","tun","woo","erg","luz","brr","gay","sip","kay","per","val","mes","ohs","now","boa","cet","pal","bar","die","war","hay","eco","pub","lob","rue","fry","lit","rex","jan","cot","bid","ali","pay","col","gum","ger","row","won","dan","rum","fad","tut","sag","yip","sui","ark","has","zip","fez","own","ump","dis","ads","max","jaw","out","btu","ana","gap","cry","led","abe","box","ore","pig","fie","toy","fat","cal","lie","noh","sew","ono","tam","flu","mgm","ply","awe","pry","tit","tie","yet","too","tax","jim","san","pan","map","ski","ova","wed","non","wac","nut","why","bye","lye","oct","old","fin","feb","chi","sap","owl","log","tod","dot","bow","fob","for","joe","ivy","fan","age","fax","hip","jib","mel","hus","sob","ifs","tab","ara","dab","jag","jar","arm","lot","tom","sax","tex","yum","pei","wen","wry","ire","irk","far","mew","wit","doe","gas","rte","ian","pot","ask","wag","hag","amy","nag","ron","soy","gin","don","tug","fay","vic","boo","nam","ave","buy","sop","but","orb","fen","paw","his","sub","bob","yea","oft","inn","rod","yam","pew","web","hod","hun","gyp","wei","wis","rob","gad","pie","mon","dog","bib","rub","ere","dig","era","cat","fox","bee","mod","day","apr","vie","nev","jam","pam","new","aye","ani","and","ibm","yap","can","pyx","tar","kin","fog","hum","pip","cup","dye","lyx","jog","nun","par","wan","fey","bus","oak","bad","ats","set","qom","vat","eat","pus","rev","axe","ion","six","ila","lao","mom","mas","pro","few","opt","poe","art","ash","oar","cap","lop","may","shy","rid","bat","sum","rim","fee","bmw","sky","maj","hue","thy","ava","rap","den","fla","auk","cox","ibo","hey","saw","vim","sec","ltd","you","its","tat","dew","eva","tog","ram","let","see","zit","maw","nix","ate","gig","rep","owe","ind","hog","eve","sam","zoo","any","dow","cod","bed","vet","ham","sis","hex","via","fir","nod","mao","aug","mum","hoe","bah","hal","keg","hew","zed","tow","gog","ass","dem","who","bet","gos","son","ear","spy","kit","boy","due","sen","oaf","mix","hep","fur","ada","bin","nil","mia","ewe","hit","fix","sad","rib","eye","hop","haw","wax","mid","tad","ken","wad","rye","pap","bog","gut","ito","woe","our","ado","sin","mad","ray","hon","roy","dip","hen","iva","lug","asp","hui","yak","bay","poi","yep","bun","try","lad","elm","nat","wyo","gym","dug","toe","dee","wig","sly","rip","geo","cog","pas","zen","odd","nan","lay","pod","fit","hem","joy","bum","rio","yon","dec","leg","put","sue","dim","pet","yaw","nub","bit","bur","sid","sun","oil","red","doc","moe","caw","eel","dix","cub","end","gem","off","yew","hug","pop","tub","sgt","lid","pun","ton","sol","din","yup","jab","pea","bug","gag","mil","jig","hub","low","did","tin","get","gte","sox","lei","mig","fig","lon","use","ban","flo","nov","jut","bag","mir","sty","lap","two","ins","con","ant","net","tux","ode","stu","mug","cad","nap","gun","fop","tot","sow","sal","sic","ted","wot","del","imp","cob","way","ann","tan","mci","job","wet","ism","err","him","all","pad","hah","hie","aim","ike","jed","ego","mac","baa","min","com","ill","was","cab","ago","ina","big","ilk","gal","tap","duh","ola","ran","lab","top","gob","hot","ora","tia","kip","han","met","hut","she","sac","fed","goo","tee","ell","not","act","gil","rut","ala","ape","rig","cid","god","duo","lin","aid","gel","awl","lag","elf","liz","ref","aha","fib","oho","tho","her","nor","ace","adz","fun","ned","coo","win","tao","coy","van","man","pit","guy","foe","hid","mai","sup","jay","hob","mow","jot","are","pol","arc","lax","aft","alb","len","air","pug","pox","vow","got","meg","zoe","amp","ale","bud","gee","pin","dun","pat","ten","mob"};
for(int i=0;i<a.length;i++) {
wordList.add(a[i]);
}
System.out.println(s.findLadders(beginWord, endWord, wordList));
System.out.println("*----------------------------------------------");
System.out.println("**************************************************");
//其他测试
System.out.println("==============================");
System.out.println(s.subOne("dot", "log"));;
Integer i = new Integer(666666);
fun(i);
System.out.println(i);
}
public static void fun(Integer i) {
i = 1;
}
}