leetcode 126. 单词接龙 II

介绍

题目链接

方法一

这是我的第一种实现方法,时间复杂度很高,没有通过全部的测试用例,具体看代码就可以了

代码

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值