[LeetCode]127. Word Ladder 深入浅出讲解和代码示例

来源:互联网 发布:win7安装apache 编辑:程序博客网 时间:2024/06/04 20:11


1、汇总概要


本题解题思路中用到了哈希、堆栈的知识点。

2、题目


Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

  1. Only one letter can be changed at a time.
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

UPDATE (2017/1/20):
The wordList parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.


3、审题


已知条件:起始单词、目的单词、词典
动作:起始单词每次变化其中一个字母,经过N次变化后,变为目的单词
求:从起始单词变化为目的单词的最小路径(N最小)

4、解题思路


以题目中的example来讲解思路。

本题的基本思路可以用暴力破解法,用多叉树的思路,找到所有从起始单词到目的单词的路径,再比较取最短路径即可。
但该方法空间复杂度消耗太大(需保存所有的多叉树路径),舍弃。

=> 本题用堆栈、哈希的思路来求解。

Step1:从起始单词到目的单词,可达路径用堆栈来保存,每次求取一组可达路径;

Step2:在迭代求取可达路径时,因已遍历过的路径不会保存,而只保留最优的一组,所以需标记记录已经迭代过的路径,这里用hash+list来设计标记。
建立个hash表,将beginWord、endWord、wordList中所有出现的单词建立一张映射表,key=word,value是一存放所有与该word相差一个字符的单词数组,如下:
{
'hit': ['hot'], 'lot': ['hot', 'dot', 'log'], 'dog': ['dot', 'log', 'cog'], 'hot': ['dot', 'lot', 'hit'], 'cog': ['dog', 'log'], 'dot': ['hot', 'dog', 'lot'], 'log': ['dog', 'lot', 'cog']}

Step3:迭代过程如下图(反复往stack中push和pop的过程)


1) 将起始单词(hit)放入stack堆栈;
2) 从hash表中查找hit对应的value,顺序从该数组中选取,此处选取"hot"放入堆栈;
3) 循环调用2),依次将"dot","dog"...等放入堆栈 (见上图中最左处stack中的值)
4) 这里说明下"lot",lot对应的value数组为[‘hot’,‘dot’,‘log’],而hot,dot,log都已在stack中,即lot后无单词可往stack中放,该路径结束(弹出lot)
5) 继续按照4)的规则,依次弹出lot,放入cog,后又弹出cog、弹出log,放入cog,一条可达路径完成,记录下该路径;
6) 继续迭代,止到所有路径都遍历完毕(结束条件为stack中只剩下底部单词hit时)

5、代码示例 - Python


import timeimport copyclass Solution:    def dist(self,word1,word2):        len1 = len(word1)        len2 = len(word2)        disNum = len1        if(len1 == len2):            for i in range(0,len1):                if (word1[i] == word2[i]):                    disNum = disNum - 1        else:            disNum = disNum + 1        return disNum    def listToDict(self,begin,wd):        #build hash + link from wordlist        wd.append(begin) #add begin into dict        lenw = len(wd)        wdict = {}        for i in range (0,lenw):            for j in range(0,lenw):                dres = self.dist(wd[i],wd[j])                if(dres == 1):                    if wdict.has_key(wd[i]):                        wdict[wd[i]].append(wd[j])                    else:                        wdict[wd[i]] = [wd[j]]                    return wdict        def ifLast(self,key,value,wdict):        valuel = wdict[key]        index = valuel.index(value)        if index == len(valuel)-1:            return 0        else:            return 1                def findLabbers(self,begin,end,wd):        wdict = self.listToDict(begin,wd)        max = len(wd) + 1        wstack = []        index = 0        wstack.append(begin)        top = 1 #top is the stack length        toppre = ""        res = [[]];        reslen = 0        #build stack        pre = ""        while wstack:            print "\n\n go while ---"            time.sleep(0.1)            '''            1. push to stack            2. loop to push until top == 1 or stack[top] = end            3. if top == 1                    pop item and go to step 2                if stack[top] = end                    save the res and pop item and go to step 2                if index + 1 > next.len                    end the loop            '''            if wstack[top-1] == end:                #get one res                if reslen == 0:                    res[reslen] = copy.deepcopy(wstack)                    reslen = reslen + 1                else:                    #find the min one                    min = len(res[0])                                        if min > top:                        while reslen > 1:                            res.pop()                            reslen = reslen - 1                        res[reslen-1] = copy.deepcopy(wstack)                     else:                        if min == top:                            res.append("")                            res[reslen] = copy.deepcopy(wstack)                            reslen = reslen + 1                        else:                            print "min<top: the result > exist res, not put into res list"                 #loop to find another res                pre = wstack.pop()                 top = top - 1                if wstack:                    pre = wstack.pop()                    top = top - 1 #when get res, pop twice                            #if checked all the res, end the loop            if top == 1:                key = wstack[top-1]                if pre != "":                    if self.ifLast(key,pre,wdict):                        break #end the all loop                        # build the stack            if wdict.has_key(wstack[top-1]):                valuel = wdict[wstack[top-1]]                #get the pre index, and loop from it                               if pre == "" or pre not in valuel: #need remove duplicate here                    index = 0;                else:                    index = valuel.index(pre)                    index = index + 1                #loop to get the item, which not in stack                while(index <= len(valuel)-1):                    if (valuel[index] in wstack):                        print "go 7 ---"                        index = index + 1;                        print "index, len(valuel)-1",index, len(valuel)-1                    else:                        break                #check whether have item to put into stack                if index <= len(valuel)-1:                       #have item to put into stack                             lenws = len(wstack)                    #get the right item into stack                    #the stack length shouldn't to be too long                    if (lenws < max):                        wstack.append(valuel[index])                    else:                        #if not the right item, pop to reloop                        pre = wstack.pop()                        top = top - 1                        continue                else:                    #no item  to put into stack, pop to reloop                    pre = wstack.pop()                    top = top - 1                    continue                top = top + 1        return res    if __name__ == "__main__":    wd = ["hot","dot","dog","lot","log","cog"]    begin = "hit"    end = "log"    st = Solution()    res = st.findLabbers(begin,end,wd)    print "\n\nget result ==============\n",res

---------------------------------------------------------------------------------------------------
本文链接:http://blog.csdn.net/karen0310/article/details/75013953
请尊重作者的劳动成果,转载请注明出处!
---------------------------------------------------------------------------------------------------

原创粉丝点击