题目描述

给定两个单词(初始单词和目标单词)和一个单词字典,请找出所有的从初始单词到目标单词的最短转换序列:
每一次转换只能改变一个单词
每一个中间词都必须存在单词字典当中
例如:
给定的初始单词start="hit",
目标单词end ="cog"。
单词字典dict =["hot","dot","dog","lot","log"]
返回的结果为:
  [↵    ["hit","hot","dot","dog","cog"],↵    ["hit","hot","lot","log","cog"]↵  ]

注意:

题目中给出的所有单词的长度都是相同的
题目中给出的所有单词都仅包含小写字母

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"]↵  ]↵

class Solution {
public:/*
    vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
        vector<vector<string>> paths;
        vector<string> path(1, start);
        if(start == end){
            paths.push_back(path);
            return paths;
        }
        unordered_set<string> forward, backward;
        forward.insert(start);
        backward.insert(end);
        unordered_map<string, vector<string>> nexts;
        bool isForward = false;
        if(findLaddersHelper(forward, backward, dict, nexts, isForward))
            getPath(start, end, nexts, path, paths);
        return paths;
    }
private:
    bool findLaddersHelper(unordered_set<string> &forward,
                           unordered_set<string> &backward,
                           unordered_set<string> &dict,
                           unordered_map<string, vector<string>> nexts,
                           bool &isForward){
        if(forward.empty())
            return false;
        if(forward.size() > backward.size())
            return findLaddersHelper(backward, forward, dict, nexts, isForward); //从words数较少的一边开始寻路
        for(auto it=forward.begin(); it!=forward.end(); it++)
            dict.erase(*it);
        for(auto it=backward.begin(); it!=backward.end(); it++)
            dict.erase(*it);
        unordered_set<string> nextLevel;
        bool reach = false;
        for(auto it=forward.begin(); it!=forward.end(); ++it){
            string word = *it;
            for(auto ch=word.begin(); ch!=word.end(); ++ch){
                char tmp = *ch;
                for(*ch='a'; *ch<='z'; ++(*ch)){
                    if(*ch != tmp) //遍历除自身外的25个字母
                        if(backward.find(word) != backward.end()){
                            reach = true; //走到了末尾
                            isForward ? nexts[*it].push_back(word) : nexts[word].push_back(*it);
                        }
                        else if(!reach && dict.find(word) != dict.end()){
                            nextLevel.insert(word);
                            isForward ? nexts[*it].push_back(word) : nexts[word].push_back(*it);
                        }
                }
            *ch = tmp;
            }
        }
        return reach || findLaddersHelper(backward, nextLevel, dict, nexts, isForward);
    }
     
    void getPath(string beginWord, string &endWord,
                 unordered_map<string, vector<string>> &nexts,
                 vector<string> &path, vector<vector<string>> &paths){
        if(beginWord == endWord)
            paths.push_back(path);
        else
            for(auto it=nexts[beginWord].begin(); it!=nexts[beginWord].end(); ++it){
                path.push_back(*it);
                getPath(*it, endWord, nexts, path, paths);
                path.pop_back();
            }
    }*/
     vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict) {
        vector<vector<string> > paths;
        vector<string> path(1, start);
        if (start == end) {//首位words相同
            paths.push_back(path);
            return paths;
        }
        unordered_set<string> forward, backward;
        forward.insert(start);
        backward.insert(end);
        unordered_map<string, vector<string> > nexts; //存储路径的矩阵
        bool isForward = false;
        if (findLaddersHelper(forward, backward, dict, nexts, isForward))
            getPath(start, end, nexts, path, paths);
        return paths;
    }
private:
    bool findLaddersHelper(
        unordered_set<string> &forward,
        unordered_set<string> &backward,
        unordered_set<string> &dict,
        unordered_map<string, vector<string> > &nexts,
        bool &isForward) {
        isForward = !isForward; //反转方向标志??
        if (forward.empty())
            return false;
        if (forward.size() > backward.size())
            return findLaddersHelper(backward, forward, dict, nexts, isForward);//从words数较少的一边开始寻路
        for (auto it = forward.begin(); it != forward.end(); ++it) //已放入前向 后向数组中的words从dict去除
            dict.erase(*it);
        for (auto it = backward.begin(); it != backward.end(); ++it)
            dict.erase(*it);
        unordered_set<string> nextLevel;
        bool reach = false; //寻路未完成
        for (auto it = forward.begin(); it != forward.end(); ++it) {//广度遍历前向数组中的每一个分支
            string word = *it;
            for (auto ch = word.begin(); ch != word.end(); ++ch) {
                char tmp = *ch;
                for (*ch = 'a'; *ch <= 'z'; ++(*ch))//遍历除自身外的25个字母
                    if (*ch != tmp)
                        if (backward.find(word) != backward.end()) { //前后向数组成功相接
                            reach = true; //寻路完成
                            isForward ? nexts[*it].push_back(word) : nexts[word].push_back(*it);
                        }
                        else if (!reach && dict.find(word) != dict.end()) { //未到达 且 字典中有需要的words
                            nextLevel.insert(word); //将新产生的分支放入临时数组,用于下次递归调用
                            isForward ? nexts[*it].push_back(word) : nexts[word].push_back(*it);
                        }
                        *ch = tmp;
            }
        }
        return reach || findLaddersHelper(backward, nextLevel, dict, nexts, isForward);
    }
    void getPath(
        string beginWord,
        string &endWord,
        unordered_map<string, vector<string> > &nexts,
        vector<string> &path,
        vector<vector<string> > &paths) {
        if (beginWord == endWord) //走到了,将path中的值压入paths
            paths.push_back(path);
        else
            for (auto it = nexts[beginWord].begin(); it != nexts[beginWord].end(); ++it) {
                path.push_back(*it);
                getPath(*it, endWord, nexts, path, paths);
                path.pop_back(); //每退出一次递归,将该层压入的值弹出
            }
    }
};


leetcode24:word-ladder-ii的更多相关文章

  1. 【leetcode】Word Ladder II

      Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation ...

  2. 18. Word Ladder && Word Ladder II

    Word Ladder Given two words (start and end), and a dictionary, find the length of shortest transform ...

  3. LeetCode :Word Ladder II My Solution

    Word Ladder II Total Accepted: 11755 Total Submissions: 102776My Submissions Given two words (start  ...

  4. [leetcode]Word Ladder II @ Python

    [leetcode]Word Ladder II @ Python 原题地址:http://oj.leetcode.com/problems/word-ladder-ii/ 参考文献:http://b ...

  5. LeetCode: Word Ladder II 解题报告

    Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation s ...

  6. [Leetcode Week5]Word Ladder II

    Word Ladder II 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/word-ladder-ii/description/ Descripti ...

  7. 126. Word Ladder II(hard)

    126. Word Ladder II 题目 Given two words (beginWord and endWord), and a dictionary's word list, find a ...

  8. leetcode 127. Word Ladder、126. Word Ladder II

    127. Word Ladder 这道题使用bfs来解决,每次将满足要求的变换单词加入队列中. wordSet用来记录当前词典中的单词,做一个单词变换生成一个新单词,都需要判断这个单词是否在词典中,不 ...

  9. [LeetCode] Word Ladder II 词语阶梯之二

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...

  10. [Leetcode][JAVA] Word Ladder II

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from ...

随机推荐

  1. Jmeter之连接数据库

    1.下载mysql驱动文件 2.移动到Jmeter目录下的lib中 3.在配置文件中使用 jdbc:mysql://127.0.0.1:3306/fns_test_bak?useUnicode=tru ...

  2. [HAOI 2017]八纵八横

    线段树分治+线形基. 线段树分治是个锤子?? 以时间轴构建线段树,把每个环以"对线段树产生影响的时间区间"的形式加入线段树即可. #include<bits/stdc++.h ...

  3. JavaScript实时显示当前时间

    1.HTML部分 <div id="div1">显示当前时间!</div> 2.css部分 #div1 { width: 700px; height: 50 ...

  4. 多测师讲解python _unttest框架001(基本格式)_高级讲师肖sir

    1.unittest基本介绍 import unittest #导入unittest模块 #class Test(unittest.TestCase): def setUp(self): #创建dri ...

  5. 动画演示Sunday字符串匹配算法——比KMP算法快七倍!极易理解!

    前言 上一篇我用动画的方式向大家详细说明了KMP算法(没看过的同学可以回去看看). 这次我依旧采用动画的方式向大家介绍另一个你用一次就会爱上的字符串匹配算法:Sunday算法,希望能收获你的点赞关注收 ...

  6. Git的介绍以及安装

    Git的简单介绍 Git是一个开源的分布式版本控制系统,可以有效,高速的处理从很小到非常大的项目管理,GIT是为了帮助linux内核开发而开发的一个开放源码的版本控制软件 Git的安装 Linux平台 ...

  7. jmeter静默压测+可视化

    静默压测自动化脚本auto_stress_test.sh #!/usr/bin/env bash export jmx_template="test2" export suffix ...

  8. C# 面试前的准备_基础知识点的回顾_01

    本系列本章来至于http://www.cnblogs.com/LionelMessi/p/4311931.html 1.try{} 里面有个Return语句,那么紧跟try后面的Finally{}会不 ...

  9. Linux命令行history

    概述 当执行命令后,系统默认会在内存记录执行过的命令 当用户正常退出时,会将内存的命令历史存放对应历史文件中,默认是~/.bash_history 登录shell时,会读取命令历史文件中记录下的命令加 ...

  10. ucore操作系统学习(三) ucore lab3虚拟内存管理分析

    1. ucore lab3介绍 虚拟内存介绍 在目前的硬件体系结构中,程序要想在计算机中运行,必须先加载至物理主存中.在支持多道程序运行的系统上,我们想要让包括操作系统内核在内的各种程序能并发的执行, ...