leetcode 332. Reconstruct Itinerary(重构行程)

2023-09-14 21:30:00

在这里插入图片描述

有一些票tickets, tickets[ i ] = [from, to], 每个出发到达城市名字都是3个大写英文字母,
同一个出发城市时,优先去字母顺序较小的到达城市。
必须先从“JFK”出发。
每个ticket必须用且只用一次,所有ticket一定会形成至少一个有效的行程(出发至到达的一路上遍历所有城市)
按顺序记录行程上的城市并返回。

思路:

很容易想到DFS。
先建graph, 然后从“JFK”出发做DFS。
因为要先去字母顺序小的城市,所以graph的邻接链表中的链表用优先队列。
DFS用visited数组记录已经访问过的点,这里不用visited,遍历过的直接从优先队列中移除。
到目前为止,看起来不像是hard的题目。

但是,DFS中按顺序记录城市会有个问题。
举个例子

JFK -> KUC, NRT
NRT -> JFK

DFS中按顺序记录节点的结果是[JFK, KUC, NRT, JFK]
也就是说从JFK出发到KUC后,瞬间转移到NRT,再回JFK,这显然是不行的,这不是一个有效的行程。

实际上,这是一个欧拉路径的问题。
在一张图中,可以从一点出发遍历所有的边,每条边只能遍历一次,那么遍历过程中的这条路径就叫做欧拉路径。如果这条路径是闭合的,那就称为欧拉回路。也就是“一笔画”。

欧拉路径会用到Hierholzer算法。算法如下:

void dfs(int ver)
{
    对于ver的所有边:
    {
        if(未访问过)
        {
            则标记为已访问 (这里从优先队列中移除访问过的点)
            dfs(这条边所连之点)
        }
    }
    ver 入栈
}
栈逆序即是路径

总结一下,还是DFS,但是不要正向记录节点,要先记录终点,倒着记录到起点。
理解为既然一定存在有效的路径,那么当一条路走不通,就去走其他相邻节点的路径,一定会有路径把这段接上。

class Solution {
    HashMap<String, PriorityQueue<String>> graph;
    List<String> res;

    public List<String> findItinerary(List<List<String>> tickets) {
        graph = new HashMap<>();
        res = new ArrayList<>();
        
        for(List<String> ticket : tickets){
            if(!graph.containsKey(ticket.get(0))){
                graph.put(ticket.get(0), new PriorityQueue<String>());
            }
            graph.get(ticket.get(0)).offer(ticket.get(1));
        }

        //DFS
        dfs("JFK");
        Collections.reverse(res);

        return res;
    }

    void dfs(String city){
        PriorityQueue<String> queue = graph.get(city);

        while(queue != null && queue.size() > 0) {
            String nextCity = queue.poll();
            dfs(nextCity);
        }
        res.add(city);
    }
}
更多推荐

Buuctf web [SUCTF 2019]EasySQL

又是一道考察sql注入的题1、起手试探(主要看看输入什么内容有正确的回显)101'1'#发现只有在输入1的情况下有正常的回显,输入0或其他字符都没有回显,所以这题就要尝试堆叠注入了。ps:(如果想尝试其他注入方法,输入以下内容需要有回显1'报错1'#正确)2、爆库1;showdatabases;3、报表1;showta

dart 学习 之 字符串插值,空变量 null,避空运算符,条件属性访问,集合字面量,箭头语法

文章目录字符串插值(Stringinterpolation)空变量null避空运算符条件属性访问集合字面量箭头语法字符串插值(Stringinterpolation)下面是一些使用字符串插值的例子:Herearesomeexamplesofusingstringinterpolation:Stringresult字符串

【实战详解】如何快速搭建接口自动化测试框架?Python + Requests

摘要:本文主要介绍如何使用Python语言和Requests库进行接口自动化测试,并提供详细的代码示例和操作步骤。希望能对读者有所启发和帮助。前言随着移动互联网的快速发展,越来越多的应用程序采用WebAPI(也称为RESTfulAPI)作为数据交换的主要方式。针对API进行自动化测试已经变得非常重要,它可以让我们快速地

Vue Hooks 让Vue开发更简单与高效

VueHooks让Vue开发更简单与高效介绍VueHooks是一个基于Vue.js的插件,它提供了一种新的方式来编写Vue组件,使得开发更加简单和高效。它借鉴了ReactHooks的概念,通过使用Hooks,我们可以在不编写类组件的情况下,实现状态管理和生命周期处理。为什么使用VueHooks在传统的Vue开发中,我们

【c语言】详解结构体

目录什么是结构体?结构体的声明结构体变量的创建和初始化匿名结构体类型结构体的自引用结构体的初始化普通初始化指定初始化结构体内存对齐对齐规则默认对齐数的修改结构体传参什么是结构体?在学习每个类型之前我们需要了解其存在的意义,即什么是结构体?为什么要引入结构体这个类型呢?我们可以想象现实中我们是如何处理一个人信息的?假设现

Win10 家庭版 - 解决应用程序无法启动,因为应用程序的并行配置不正确的问题(System Default Context”的激活上下文生成失败)

Win10家庭版-解决应用程序无法启动,因为应用程序的并行配置不正确的问题(SystemDefaultContext”的激活上下文生成失败)系统环境遇到问题试过过程解决办法前天的时候,女盆友公司电脑遇到个问题:几乎所有的exe程序和软件都不能启动或者运行。我的第一个解决办法:重装即可。结果人家嫌挨个重装太麻烦。于是乎,

收款码的费率都是多少

不管是微信还是支付宝,商户最低的收款手续费率可以达到0.2%费率。一般我们普通商户的收款费率一般在0.6左右,当然也有使用0.3的,也就是1万元的费率是30-60块钱,对于一些流水比较大的商家来说,确实很有必要把这个手续费率降低。什么是收款手续费率?因为不管是微信还是支付宝,都是盈利性质的公司,他们开发了收款码这个功能

归并排序的思想

归并排序是一种基于分治思想的经典排序算法。它将待排序的数组分成两个部分,然后递归地对这两个部分进行排序,最后再将排序好的两个部分归并成一个有序的数组。具体实现过程如下:1.将待排序数组不断二分,直到只剩下一个元素,此时该元素就是有序的。2.将相邻的两个有序数组合并成一个有序数组。合并时,对于两个数组中首位元素进行比较,

SpringBoot中Filter和Interceptor快速入门

一、Filter1.定义说明:filter文件里面DemoFilter类实现Filter接口。packagecom.itheima.filter;importjavax.servlet.*;importjavax.servlet.annotation.WebFilter;importjava.io.IOExceptio

计算机二级python基础题刷题笔记(三)

hello,看到三的小伙伴们你们已经超过30%的对手啦!接下来也要加油呀代码没有最好,只有更好,如果你有更好的想法答案欢迎在评论区里发表呀1、将程序里定义好的std列表里的姓名和成绩与已经定义好的模板拼成一段话,显示在屏幕里。std=[['张三',90,87,95],['李四',83,80,87],['王五',73,5

临沂ITSS认证流程,认证条件

ITSS认证流程,认证条件一、ITSS的意义ITSS认证——信息技术服务标准,是在工业和信息化部、国家标准化委的领导和支持下,由ITSS工作组研制的一套IT服务领域的标准库和一套提供IT服务的方法论。ITSS认证-信息技术服务标准是一套成体系和综合配套的信息技术服务标准库,全面规范了IT服务产品及其组成要素,用于指导实

热文推荐