Word Ladder II

 Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) fromstart to end, such that:

  1. Only one letter can be changed at a time
  2. Each intermediate word must exist in the dictionary

For example,

Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

Return

  [
    ["hit","hot","dot","dog","cog"],
    ["hit","hot","lot","log","cog"]
  ]

Note:

  • All words have the same length.
  • All words contain only lowercase alphabetic characters.


public class Solution {
	public ArrayList<ArrayList<String>> res;
	public String end;
	public int target_length;
	public ArrayList<String> temp_list;

	public ArrayList<ArrayList<String>> findLadders(String start, String end,
			HashSet<String> dict) {
		// Start typing your Java solution below
		// DO NOT write main() function
		res = new ArrayList<ArrayList<String>>();
		temp_list = new ArrayList<String>();
		this.end = end;
		if (start.length() != end.length())
			return res;
		if (start.equals(end)) {
			temp_list.add(start);
			temp_list.add(end);
			res.add(temp_list);
			return res;
		}
		target_length = shortestLength(start, end, dict);
		int current_length = 1;
		temp_list.add(start);
		DFS(start, current_length, dict);
		return res;
	}

	private void DFS(String start, int current_length, HashSet<String> dict) {
		current_length++;
		if (current_length > target_length)
			return;
		Stack<String> stack = new Stack<String>();
		HashSet<String> valid_neighbor = nextHit(start, dict);
		for (String str : valid_neighbor)
			stack.push(str);
		while (!stack.isEmpty()) {
			String s = stack.pop();
			temp_list.add(s);
			DFS(s, current_length, dict);
			if (s.equals(end) && current_length == target_length)
				res.add(new ArrayList<String>(temp_list));
			temp_list.remove(temp_list.size() - 1);
		}
	}

	private int shortestLength(String start, String end, HashSet<String> dict) {
		if (start.length() != end.length())
			return 0;
		if (start.equals(end))
			return 2;
		int path = 0;

		Queue<String> queue = new LinkedList<String>();
		queue.offer(start);
		HashSet<String> hitted = new HashSet<String>();
		hitted.add(start);
		int queue_counter = 1;

		while (!queue.isEmpty()) {
			String s = queue.poll();
			queue_counter--;
			HashSet<String> valid_neighbor = nextHit(s, dict, hitted);
			for (String str : valid_neighbor) {
				if (str.equals(end))
					return path + 2;
				else
					queue.offer(str);
			}
			if (queue_counter == 0) {
				path++;
				queue_counter = queue.size();
			}
		}
		return 0;
	}

	private HashSet<String> nextHit(String s, HashSet<String> dict,
			HashSet<String> hitted) {
		HashSet<String> valid_neighbor = new HashSet<String>();
		for (int len = 0; len < s.length(); len++) {
			StringBuilder sb = new StringBuilder(s);
			for (char ch = 'a'; ch <= 'z'; ch++) {
				sb.setCharAt(len, ch);
				String test_case = sb.toString();
				if ((dict.contains(test_case) || test_case.equals(end))&& !hitted.contains(test_case)) {
					hitted.add(test_case);
					valid_neighbor.add(test_case);
				}
			}
		}
		return valid_neighbor;
	}

	private HashSet<String> nextHit(String s, HashSet<String> dict) {
		HashSet<String> valid_neighbor = new HashSet<String>();
		for (int len = 0; len < s.length(); len++) {
			StringBuilder sb = new StringBuilder(s);
			for (char ch = 'a'; ch <= 'z'; ch++) {
				sb.setCharAt(len, ch);
				String test_case = sb.toString();
				if (dict.contains(test_case) || test_case.equals(end)) {
					valid_neighbor.add(test_case);
				}
			}
		}
		return valid_neighbor;
	}
}
String start and end are not included in the dictionary, which is different from Word Ladder I. Need special attention to this factor when generating a valid_neighbor set.

Based on WordLadder I and DFS

Passed on judge small, but failed on judge large.

你可能感兴趣的:(Word Ladder II)