Leetcode.126 单词接龙 II

news2024/12/26 11:24:15

题目链接

Leetcode.126 单词接龙 II

题目描述

按字典 wordList完成从单词 beginWord到单词 endWord转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> ... -> sk这样的单词序列,并满足:

每对相邻的单词之间仅有单个字母不同

转换过程中的每个单词 s i ( 1 < = i < = k ) s_i(1 <= i <= k) si1<=i<=k必须是字典 wordList 中的单词。注意,beginWord不必是字典 wordList中的单词。
s k = = e n d W o r d s_k == endWord sk==endWord

给你两个单词 beginWordendWord,以及一个字典 wordList。请你找出并返回所有从 beginWordendWord 的 最短转换序列 ,如果不存在这样的转换序列,返回一个空列表。每个序列都应该以单词列表 [ b e g i n W o r d , s 1 , s 2 , . . . , s k ] [beginWord, s_1, s_2, ..., s_k] [beginWord,s1,s2,...,sk] 的形式返回。

示例 1:

输入:beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
输出:[[“hit”,“hot”,“dot”,“dog”,“cog”],[“hit”,“hot”,“lot”,“log”,“cog”]]
解释:存在 2 种最短的转换序列:
“hit” -> “hot” -> “dot” -> “dog” -> “cog”
“hit” -> “hot” -> “lot” -> “log” -> “cog”

示例 2:

输入:beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”]
输出:[]
解释:endWord “cog” 不在字典 wordList 中,所以不存在符合要求的转换序列。

提示:

  • 1 < = b e g i n W o r d . l e n g t h < = 5 1 <= beginWord.length <= 5 1<=beginWord.length<=5
  • e n d W o r d . l e n g t h = = b e g i n W o r d . l e n g t h endWord.length == beginWord.length endWord.length==beginWord.length
  • 1 < = w o r d L i s t . l e n g t h < = 500 1 <= wordList.length <= 500 1<=wordList.length<=500
  • w o r d L i s t [ i ] . l e n g t h = = b e g i n W o r d . l e n g t h wordList[i].length == beginWord.length wordList[i].length==beginWord.length
  • b e g i n W o r d 、 e n d W o r d 和 w o r d L i s t [ i ] beginWord、endWord 和 wordList[i] beginWordendWordwordList[i] 由小写英文字母组成
  • b e g i n W o r d ! = e n d W o r d beginWord != endWord beginWord!=endWord
  • w o r d L i s t wordList wordList 中的所有单词 互不相同

分析:

本题在 127. 单词接龙 的基础之上,还要记录最短的路径,求所有的最短路径。

一般这种 求一些路径 我们可以使用 回溯 来解决。

如图,我们要求 起点hit终点cog 的最短路径。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路:

  • 先用一个哈希表 uset 记录所有的单词
  • 用一个列表 path 记录路径,合法的 在uset中的单词 才插入到path中。
  • 如果遍历到的 当前字符串 c u r = = e n d W o r d cur == endWord cur==endWord,说明找到了终点。根据情况将 path 加入到结果列表 res 中:
    • 如果此时的 path.size() < min_d(初始化为无穷大,用来记录最短路径的长度的),说明又找到了一条更短的路径,所以之前记录在 res 中的路径全部清空,再加入path 同时 min_d 更新为 path.size()。
    • 如果此时的 path.size() == min_d,说明又找到一条相同长度的最短路径,此时将path 直接加入 res即可。

代码:

class Solution {
public:
    //记录 wordList 中的单词
    unordered_set<string> uset;
    //记录结果路径
    vector<vector<string>> res;
    //最短路径长度
    int min_d = 1e9;

    void dfs(string cur,string endWord,vector<string>& path,unordered_set<string>& visited){

        if(cur == endWord){
            int len = path.size();
            if(len < min_d){
                min_d = len;
                res.clear();
                res.push_back(path);
            }
            else if(len == min_d) res.push_back(path);

            return ;
        }

        //此时path.size() > min_d,说明此时的path中肯定不是最短路径 直接返回即可
        if(path.size() > min_d) return ;


        int n = cur.size();
        //从 cur 的每一个位置,都从 'a' 到 'z' 枚举
        for(int i = 0;i < n;i++){
            char op = cur[i];
            for(char c = 'a';c <= 'z';c++){
                //如果 c 与 原字符 op 一样 直接跳过本次循环
                if(op == c) continue;

                cur[i] = c;

                if(uset.count(cur)){
                    //如果已经访问过这个点 也直接跳过本次循环
                    if(visited.count(cur)) continue;
                    
                    //记录新的点
                    visited.insert(cur);
                    path.push_back(cur);

                    dfs(cur,endWord,path,visited);

                    //回溯 恢复现场
                    visited.erase(cur);
                    path.pop_back();
                }
            }
            cur[i] = op;
        }

    }

    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        unordered_set<string> visited;
        vector<string> path;

        for(auto &s:wordList) uset.insert(s);

        //如果 wordList 不包含 endWord 直接返回空列表
        if(!uset.count(endWord)) return res;

        //path 此时先加入起点
        path.push_back(beginWord);
        //因为是无向图 所以用一个哈希表来记录 已经访问过的点
        visited.insert(beginWord);

        dfs(beginWord,endWord,path,visited);


        return res;
    }
};

但是这份代码会超时。。。

在这里插入图片描述

解法二:

  • 我们可以先通过 BFS,建出一个最短路径的反向图(因为本质上我们是在求 图的最短路问题,而且因为反向图比较好建)。

建好的图应该是以下这个样子:

在这里插入图片描述

  • 所以我们第二步只需要从终点到起点 DFS 即可。

代码:

class Solution {
public:
   //记录结果
    vector<vector<string>> res;
    //图
    unordered_map<string,vector<string>> g;
    vector<string> path;
    string t;


    void dfs(string u){
        if(u == t){
           //因为从终点到起点 所以我们要逆序加入结果列表
            res.emplace_back(path.rbegin(),path.rend());
            return;
        }

        for(auto &v:g[u]){
            path.push_back(v);
            dfs(v);
            //回溯 恢复现场
            path.pop_back();
        }
    }

    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        //记录从起点开始的长度
        unordered_map<string,int> dist;
        //记录 wordList 的单词
        unordered_set<string> uset(wordList.begin(),wordList.end());
        queue<string> q;

        //起点距离为0
        dist[beginWord] = 0;
        q.push(beginWord);

        while(!q.empty()){
            auto cur = q.front();
            q.pop();

            auto next_str = cur;
            int n = cur.size();


            for(int i = 0;i < n;i++){
                char op = next_str[i];
                for(char c = 'a';c <= 'z';c++){
                    if(c == op) continue;
                    next_str[i] = c;
                    if((uset.count(next_str)) && (!dist.count(next_str) || dist[next_str] == dist[cur] + 1)){
                        //建反向边
                        g[next_str].push_back(cur);
                    }
                    //点 s 是没有访问过的点
                    if(uset.count(next_str) && !dist.count(next_str)){
                        dist[next_str] = dist[cur] + 1;
                        //如果 next_str 是终点,直接跳出循环
                        if(next_str == endWord) break;
                        q.push(next_str);
                    }
                }
                next_str[i] = op;
            }
        }


        //判断从起点能否到达终点 不能直接返回空列表
        if(!dist.count(endWord)) return res;

        //path 加入终点 倒着 dfs
        path.push_back(endWord);
        

        t = beginWord;

        dfs(endWord);

        return res;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/175155.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《高效能团队模式》读书笔记2

如果我们将团队类型的数量缩减为四类基本团队拓扑&#xff0c;这个问题就迎刃而解了。 流动式团队 赋能团队 复杂子系统团队 平台团队只要使用得当&#xff0c;这四类团队拓扑能够满足构建和运行现代软件系统的需要。结合有效的软件边界&#xff08;第6章&#xff09;和团队交互…

Java注解,元注解,自定义注解的使用

Java注解&#xff0c;元注解&#xff0c;自定义注解的使用Java注解基本的注解1.Override2.Deprecated3.SuppressWarnings4.SafeVarargs5.FunctionalInterfaceJava提供的元注解1.Retention2.Target3.Documented4.Inherited自定义注解自定义注解的使用Java注解 从JDK5开始,Java增…

从旺店通·企业奇门到用友U8通过接口集成数据

接入系统&#xff1a;旺店通企业奇门慧策&#xff08;原旺店通&#xff09;是一家技术驱动型智能零售服务商&#xff0c;基于云计算PaaS、SaaS模式&#xff0c;以一体化智能零售解决方案&#xff0c;帮助零售企业数字化智能化升级&#xff0c;实现企业规模化发展。对接系统&…

本地数仓项目(四)—— 即席查询

1 背景 本文描述本地数仓项目即席查询相关内容&#xff0c;主要涉及即席查询工具包括Presto、Druid、Kylin。 本文基于文章《本地数据仓库项目(一) —— 本地数仓搭建详细流程》 和《本地数仓项目(二)——搭建系统业务数仓详细流程》以及《本地数仓项目(三&#xff09;—— 数…

金蝶云星辰和旺店通企业版奇门单据接口集成

金蝶云星辰V1和旺店通企业奇门单据接口集成对接源平台:旺店通企业奇门慧策&#xff08;原旺店通&#xff09;是一家技术驱动型智能零售服务商&#xff0c;基于云计算PaaS、SaaS模式&#xff0c;以一体化智能零售解决方案&#xff0c;帮助零售企业数字化智能化升级&#xff0c;实…

图的基本概念以及表示方法(链式前向星重点理解,简单易懂版)

图表示一个集合中元素之间存在的多对多关系的一种数据结构。 图的一些定义 &#xff1a; 1.图由顶点和连接顶点的边构成&#xff0c;即G ( V , E ) &#xff0c;其中V为顶点集合&#xff0c;E为边的集合。2.边表示两个顶点之间存在某种关系&#xff0c;边表示为&#xff08;…

Elasticsearch7.8.0版本高级查询—— 单字段排序文档

目录一、初始化文档数据二、单字段排序文档2.1、概述2.2、示例一、初始化文档数据 在 Postman 中&#xff0c;向 ES 服务器发 POST 请求 &#xff1a;http://localhost:9200/user/_doc/1&#xff0c;请求体内容为&#xff1a; { "name":"zhangsan", "…

可笑 在网页上复制点东西 还需要money?进来看~

前言 哈喽 大家好&#xff01; 我是木易巷&#xff0c;我回来啦&#xff01;&#xff01;&#xff01; 现在好多平台都变成了不开会员不能复制这样的情况。士可杀不可辱&#xff01;作为一个优秀的复制粘贴工程师&#xff0c;在网页上复制点东西&#xff0c;还需要我掏钱&#…

【Springboot】idea中配置文件不生效、自动提示功能消失、小绿标不出现现象

怎么解决idea中配置文件不生效、自动提示功能消失、小绿标不出现现象先要明确一个核心&#xff0c;就是自动提示功能不是SpringBoot技术给我们提供的&#xff0c;是我们在Idea工具下编程&#xff0c;这个编程工具给我们提供的。明白了这一点后&#xff0c;再来说为什么会出现这…

07.C语言文件操作

1. 使用文件的原因我们前面学习结构体时&#xff0c;写了通讯录的程序&#xff0c;当通讯录运行起来的时候&#xff0c;可以给通讯录中增加、删除数据&#xff0c;此时数据是存放在内存中&#xff0c;当程序退出的时候&#xff0c;通讯录中的数据自然就不存在了&#xff0c;等下…

盒模型 盒子的组成部分 1. 内容 content 2. 填充 (内边距) padding 3. 边框 border 4. 外边距 margin

目录盒模型盒子的组成部分1. 内容 content2. 填充 (内边距) padding3. 边框 border4. 外边距 margin盒模型 box&#xff1a;盒子&#xff0c;每个元素在页面中都会生成一个矩形区域&#xff08;盒子&#xff09; 盒子类型&#xff1a; 行盒&#xff0c;display等于inline的元…

使用Seq2Seq实现中英文翻译

介绍 Deep NLP 自然语言处理NLP是计算机科学、人工智能和语言学交叉领域的分支科学&#xff0c;主要让计算机处理和理解自然语言&#xff0c;如机器翻译、问答系统等。但因其在学习和使用语言的复杂性&#xff0c;通常认为NLP是困难的&#xff0c;近几年&#xff0c;随着深度…

MedCalc:生物医学研究的统计软件 Crack

MedCalc&#xff1a;生物医学研究的统计软件 MedCalc是用于生物医学研究的统计软件包&#xff0c;统计数据包括 220 多个统计测试、程序和图表&#xff0c;ROC曲线分析、方法比较和质量控制工具。 简单易学&#xff0c;快速可靠 MedCalc 包括 220 多种统计测试、程序和图表 RO…

springboot+vue整合JustAuth实现第三方登录

前后端分离版实现第三方登录&#xff1a;GITEE为例 1&#xff1a;首先maven安装依赖&#xff1a; <!-- oauth工具类 --><dependency><groupId>com.xkcoding.justauth</groupId><artifactId>justauth-spring-boot-starter</artifactId><…

学习wifi操作模块simplewifi的基本用法

之前学习Python的过程中学过基于pywifi模块操作wifi连接的用法&#xff0c;在dotnet中&#xff0c;SimpleWifi也支持类似的功能。SimpleWifi是C#语言编写的在Windows系统中管理wifi连接的库&#xff0c;它抽象并封装了Managed Wifi API中的wifi操作相关函数&#xff0c;更易于使…

词向量与语言模型

本篇博客是对于 https://www.cnblogs.com/nickchen121/p/15105048.html#%E7%AC%AC%E4%B8%80%E7%AF%87-transformergptbert%E9%A2%84%E8%AE%AD%E7%BB%83%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B%E7%9A%84%E5%89%8D%E4%B8%96%E4%BB%8A%E7%94%9F%E7%90%86%E8%AE%BA的归纳 先来了解一…

django,uwsgi,nginx部署配置要点整理

注意&#xff1a; 1.只对关键点进行整理&#xff1a; 2.python_test是项目名称 环境&#xff1a; python:v3.10.9 1.部署前&#xff0c;执行 python manage.py check --deploy 根据提示进行部署检查&#xff0c;调整&#xff0c;ssl相关的可以不做调整 2.settings.py最终版…

Java的类型擦除与泛型的关系

在讨论类型擦除之前&#xff0c;我们必须先来了解一下java的泛型。所谓的泛型就是参数化的类型。这就意思着我们可以具体的类型作为一个参数传递给方法、类、接口。 为什么我们需要泛型呢&#xff1f;首先我们都知道在java里&#xff0c;Object就是对象的父类。Object可以引用…

收集两篇关于前端不错的文章

深以为然&#xff01; 为什么我建议前端框架优先选 Vue 而不是 React https://acejoy.com/2022/03/10/675/ 我两者都用过比较长的时间。网上各种“为什么我选React放弃了Vue”或者“为什么我选Vue放弃了React”之类的文章很多&#xff0c;实际都没什么用&#xff0c;必须要真…

Windows使用Paddle训练好的模型进行OpenVino推理引擎下的部署

目录一. Openvino下载二. 准备模型2.1 导出Paddle Inference模型2.2 转换为ONNX模型2.3 转换为ONNX模型2.3.1 获取部署代码2.3.2 环境准备2.3.3 编译一. Openvino下载 根据Paddle官方的描述&#xff0c;当前检测模型转换为openvino格式是有问题的&#xff0c;暂时只支持分割和…