bailuo

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start 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.  

  本题是求路径的,立刻会联想到两种比较常见的求路径的方法,深搜和广搜。使用深搜一般问题都会有递归的特质,当答案生成到一半时,就进行判断,抛弃不满足要求的答案,所以深搜会比暴力搜索法要快。本题的话,很难找到一个递归函数去求所有的解。因此我们选用广搜,一般广搜没有什么特征,如果是树或者是图,概率更大。求路径的长度,状态里面需要存路径的长度;如果是求路径本身或者动作序列,需要一棵树存储广搜过程中的路径,如果能够预估状态个数的上限,就开一个大数组,用树的双亲表示法。如果不能预估状态总数,则要用一棵通用的树。本题的话,我是使用了一个LinkedList来保存搜索过程中路径。除此之外,广搜需要一个队列,用于一层一层的扩展。在本题中,queue保存的是有效状态,用题目的给的条件举个具体的例子,queue最先保存的是“hit”,这也是我们所谓的第一层,接着往下继续执行,“hit”出队列,“hot”进队列,这是第二层,第三层queue里面就是{"dot","lot"}...我们用一个HashMap用于记录搜索过程中的中间状态,提高搜索的效率。最后,递归的将每一组有效的路径写进最后的数组中。

class Node
{
    int level;
    String value;
    LinkedList<Node> prev;

    public Node(int level, String value)
    {
        this.level = level;
        this.value = value;
    }

    void addPrev(Node node)
    {
        if (prev == null || prev.size() == 0)
        {
            prev = new LinkedList<Node>();
        }
        prev.add(node);
    }
}

public class Solution
{
    ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();

    public void findPath(Node endNode, ArrayList<String> current, String start)
    {
        if (endNode.value.equals(start))
        {
            result.add(current);
            return;
        }

        ArrayList<String> tempList;
        for (Node node : endNode.prev)
        {
            tempList = new ArrayList<String>(current);
            tempList.add(0, node.value);
            findPath(node, tempList, start);
        }
    }

    public ArrayList<ArrayList<String>> findLadders(String start, String end,
            Set<String> dict)
    {
        HashMap<String, Node> hashMap = new HashMap<String, Node>();
        Queue<Node> queue = new LinkedList<Node>();
        Node node = new Node(0, start);
        queue.add(node);
        Node endNode = null;
        hashMap.put(start, node);
        boolean isFound = false;
        boolean flag = false;
        while (queue.size() > 0 && !isFound)
        {
            int queueLength = queue.size();
            for (int k = 0; k < queueLength; k++)
            {
                node = queue.poll();
                for (int i = 0; i < node.value.length(); i++)
                {
                    StringBuilder word = new StringBuilder(node.value);
                    for (char j = 'a'; j <= 'z'; j++)
                    {
                        word.setCharAt(i, j);
                        if (word.toString().equals(end))
                        {
                            if (!flag)
                            {
                                Node temp = new Node(node.level + 1, word.toString());
                                flag = true;
                                temp.addPrev(node);
                                endNode = temp;
                                isFound = true;
                            }else {
                                endNode.addPrev(node);
                                isFound = true;
                            }                            
                        }
                        if (dict.contains(word.toString()))
                        {
                            Node newNode = hashMap.get(word.toString());
                            if (newNode == null)
                            {
                                Node addNode = new Node(node.level + 1,
                                        word.toString());
                                addNode.addPrev(node);
                                hashMap.put(word.toString(), addNode);
                                queue.add(addNode);
                            } else
                            {
                                if (newNode.level == node.level + 1)
                                {
                                    newNode.addPrev(node);
                                }
                            }
                        }
                    }
                }
            }
        }
        if (endNode != null )
        {
            findPath(endNode, new ArrayList<String>(Arrays.asList(end)),
                    start);
        }
        return result;
    }
    
}
 

 

posted on 2014-10-22 22:09  bailuo  阅读(159)  评论(0)    收藏  举报