渣中渣的Word ladder 1+2 Leetcode


渣中渣這次只能上IDE了,代碼太長了,老有筆誤。結果還調試了半天,還超時,最後改了一上午才過,坑爹啊,面試要是面到這個題,哥們就讓你們見識見識什麼叫翔尿齊飛!996ms險過.......

public class Solution {
   HashSet<String> dictmap;
	HashSet<String> rSet = new HashSet<String>();
	ArrayList<ArrayList<String>> reslist = new ArrayList<ArrayList<String>>();
	Character[] ch;
	boolean debug = false;

	public ArrayList<String> getNext(String ts) {
		ArrayList<String> candis = new ArrayList<String>();
		char[] ss = ts.toCharArray();
		String res = null;
		for (int j = 0; j < ss.length; j++) {
			ss = ts.toCharArray();
			for (int i = 0; i < ch.length; i++) {
				ss[j] = ch[i];
				res = String.valueOf(ss);
				if (dictmap.contains(res) && !res.equals(ts)) {
					candis.add(res);
				}
			}
		}
//		if (debug)
//			System.out.println("get next form [" + ts + "] as " + candis);
		return candis;
	}

	public ArrayList<ArrayList<String>> findLadders(String start, String end,
			HashSet<String> dict) {
		dict.remove(start);
		dict.add(end);
		dictmap = dict;
		ch = new Character[26];
		ch[0] = 'a';
		for (int i = 0; i < ch.length; i++)
			ch[i] = (char) (ch[0] + i);
		dictBFS2(start, end);
		return reslist;

	}

	private ArrayList<ArrayList<String>> dictBFS2(String start, String end) {
		// this time we need to record the path they goes
		ArrayList<String> ways = new ArrayList<String>();
		// used to save the bfs level
		ArrayList<Integer> steps = new ArrayList<Integer>();
		// save the father position for result
		HashMap<String, ArrayList<Integer>> fatherp = new HashMap<String, ArrayList<Integer>>();
		// save where the end goes
		ArrayList<Integer> endplace = new ArrayList<Integer>();
		//

		int currentStep = 0;
		int cnumber = 0;
		HashSet<String> stageSet=new HashSet<String>();
		ways.add(start);
		fatherp.put(start, null);
		steps.add(1);
		while (cnumber < ways.size()) {
			// System.out.println("cnumber="+cnumber+" size="+ways.size());
			String father = ways.get(cnumber);
			ArrayList<String> sons = getNext(father);
			for (String son : sons) {
				if (son.equals(end)){
					if(debug)
						System.out.println("record end as"+cnumber);
					endplace.add(cnumber);
					ways.add(son);
				}
				else {
					rSet.add(son);
					ArrayList<Integer> tmplist = fatherp.get(son);
					if (tmplist == null) {
						tmplist = new ArrayList<Integer>();
						fatherp.put(son, tmplist);
						ways.add(son);
					}
					tmplist.add(cnumber);
					if (debug)
					System.out.println("son ["+son+"] add "+cnumber);
					// dictmap.remove(son);
				}
				
				// System.out.println("adding  "+son);
			}
			cnumber++;
			if (cnumber == steps.get(currentStep)) {
				if (endplace.size() > 0)
					break;
				if (debug)
					System.out.println("next level");
				dictmap.removeAll(rSet);
				rSet.clear();
				currentStep++;
				steps.add(ways.size());
			}
		}
		if(debug){
			for(String sw:ways)
				System.out.print(sw+" ");
			System.out.println();
			int i=0;
			for(String sw:ways)
				System.out.print("  "+i+++" ");
			System.out.println();
		}
			
		// gen res1
		{
			Stack<String> sts = new Stack<String>();
			sts.push(end);
			HashSet<String> usedSet=new HashSet<String>();
			for (int j : endplace) {
				if (debug)
				System.out.println("j="+ j);
				if(usedSet.contains(ways.get(j)))
					continue;
				usedSet.add(ways.get(j));
				genRes(ways, j, fatherp, sts);
//				sts.remove(sts.size() - 1);
			}
		}
		//gen res2
		{
			
		}
		
		return reslist;
	}

	public void debuglist(Stack<String> sts){
		if (debug){
		System.out.print("[STS]:   ");
		for(int i=0;i<sts.size();i++)
			System.out.print(sts.get(i)+ " ");
		System.out.println();
		}
	}
	private void genRes(ArrayList<String> ways, int place,
			HashMap<String, ArrayList<Integer>> fatherp, Stack<String> sts) {
		int ep = place;
		String ts = ways.get(ep);
		if (debug)
		System.out.println("get place " + place + " as " + ts);
		sts.push(ts);
		debuglist(sts);
		ArrayList<Integer> lis = fatherp.get(ts);
		if (lis == null) {
			ArrayList<String> resp = new ArrayList<String>();
			for(int i=sts.size()-1;i>=0;i--)
				resp.add(sts.get(i));
			reslist.add(resp);
			if (debug)
			System.out.println();
			String sst=sts.pop();
			if (debug)
			System.out.println("remove last as "+sst);
			debuglist(sts);
			return;
		}
		for (int j : lis) {
			genRes(ways, j, fatherp, sts);
		}
		String sst=sts.pop();
		if (debug)
		System.out.println("remove  in for last as "+sst);
		debuglist(sts);

	}
}


180行 看着想哭的心都有了。 其實這個題就是一個圖遍歷。

但要注意:

假設又M個單詞,每個單詞長度是L

1. 遍歷方式肯定是單詞到單詞,但是是先做好遍歷表呢,還是循環單詞呢?

這裏其實有個優化問題,如果每個單詞的lenth足夠長,就應該先取O(M2)獲得連通圖

這裏單詞都很短,乾脆26個字母循環試試,加上dict用hashmap實現,也不慢,時間應該是O(26*L*Map查找時間)但顯然這種比上一種M方的要快,所以ladder 1 還是2裏都是用的這種。


2.  然後就相對簡單了,就是個樹形圖(其實圖裏有環!!而且有很多種環,這就是Ladder2坑爹的原因之一)。Ladder1是求最短距離,不用考慮環的問題,BFS的時候每用一個節點就刪除一個dict裏的節點就好,爲什麼?因爲使用了環也不會獲得更短路徑。爲什麼?因爲BFS是層次遍歷,目前既然能遍歷到節點X,那麼之前的層次一定不能遍歷到節點X,X最短路徑一定是在這一層。即使本層有其他節點可能作爲X的父節點,對層次結構來說是不影響結果的。

所以Ladder1結果就出來了,某層出現end,那就返回層數就ok。


3. Ladder2就坑爹的多了,建立圖結構的時候有兩種構建方法需要注意,一種方式就是同層環可以化爲無環的兩個甚至多個節點,另一種就直接用帶環的樹結構。那就是對同層環的處理。因爲需要遍歷所有最短路徑,因此同層環不能被忽略。這時,整個處理過程被劃分爲兩部分,

1. 通過BFS尋找end

2. 找到end後,以end爲根節點反向遍歷路徑並寫出全部路徑。 這裏應該是個DFS


如果按照無環做法,即沒出現一次子節點就列一次子節點,會在生成結果的時候超時。 我沒太想明白爲什麼,估計是我的代碼裏有bug


渣又優化了一下,用了個數據結構,結果因爲String 和Node比較的bug改了20分鐘,請叫我渣中渣

優化後代碼960ms險過

HashMap<String, Node> dictmap = new HashMap<String, Node>();
	HashSet<String> dictSet;
	ArrayList<ArrayList<String>> reslist = new ArrayList<ArrayList<String>>();
	Character[] ch;
	boolean debug = false;

	class Node {
		String value;
		ArrayList<Node> fathers = new ArrayList<Node>();

		public Node(String s) {
			value = s;

		}

		public void addFather(Node e) {
			fathers.add(e);
		}

		@Override
		public boolean equals(Object obj) {
			Node t = (Node) obj;
			return t.value == value;
		}

		@Override
		public String toString() {
			return value;
		}
	}

	public ArrayList<Node> getNext(Node ts) {
		ArrayList<Node> candis = new ArrayList<Node>();
		char[] ss = ts.value.toCharArray();
		String res = null;
		for (int j = 0; j < ss.length; j++) {
			ss = ts.value.toCharArray();
			for (int i = 0; i < ch.length; i++) {
				ss[j] = ch[i];
				res = String.valueOf(ss);
				if (dictSet.contains(res) && !res.equals(ts.value)) {
					// any new gen node will added into dictmap
					if (!dictmap.containsKey(res)) {
						Node n = new Node(res);
						dictmap.put(res, n);
					}
					Node n = dictmap.get(res);
					n.addFather(ts);
					candis.add(n);
				}
			}
		}
		return candis;
	}

	public ArrayList<ArrayList<String>> findLadders(String start, String end,
			HashSet<String> dict) {
		dict.remove(start);
		dict.add(end);
		dictSet = dict;
		ch = new Character[26];
		ch[0] = 'a';
		for (int i = 0; i < ch.length; i++)
			ch[i] = (char) (ch[0] + i);
		dictBFS3(start, end);
		return reslist;

	}

	private void dictBFS3(String start, String end) {
		ArrayList<Node> nodelist = new ArrayList<Node>();
		ArrayList<Integer> steps = new ArrayList<Integer>();
		HashSet<Node> reachset = new HashSet<Node>();
		HashSet<String> levelset = new HashSet<String>();
		int currentStep = 0;
		int l = 0;
		nodelist.add(new Node(start));
		steps.add(1);
		while (l < nodelist.size()) {
			Node tnode = nodelist.get(l);
			ArrayList<Node> sonlist = getNext(tnode);
			for (Node son : sonlist) {
				// if have son, this should be the last step and save it's
				// father in a set
				if (son.value.equals(end)) {
					reachset.add(tnode);
					continue;
				} else {
					if (!levelset.contains(son.value)) {
						levelset.add(son.value);
						nodelist.add(son);
					}
				}
			}
			l++;
			if (l == steps.get(currentStep)) {
				if (reachset.size() > 0)
					break;
				dictSet.removeAll(levelset);
				steps.add(nodelist.size());
				currentStep++;
			}

		}
		Stack<String> res = new Stack<String>();
		res.push(end);
		for (Node node : reachset) {
			genRes(node, res, start);
		}
	}

	public void genRes(Node node, Stack<String> res, String start) {
		if (node.fathers.size() == 0) {
			ArrayList<String> list = new ArrayList<String>();
			list.add(start);
			for (int i = res.size() - 1; i >= 0; i--)
				list.add(res.get(i));
			reslist.add(list);
			return;
		}
		res.add(node.value);
		for (Node tnode : node.fathers) {
			genRes(tnode, res, start);
		}
		res.pop();
	}




剛總結完,看一個神的blog說,這題對面試準備不大~~~~~ 我CCCCCCCC



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