LeetCode:1997. 访问完所有房间的第一天(DP Java)

2024-03-30 16:12

本文主要是介绍LeetCode:1997. 访问完所有房间的第一天(DP Java),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1997. 访问完所有房间的第一天

题目描述:

实现代码与解析:

DP

原理思路:


1997. 访问完所有房间的第一天

题目描述:

你需要访问 n 个房间,房间从 0 到 n - 1 编号。同时,每一天都有一个日期编号,从 0 开始,依天数递增。你每天都会访问一个房间。

最开始的第 0 天,你访问 0 号房间。给你一个长度为 n 且 下标从 0 开始 的数组 nextVisit 。在接下来的几天中,你访问房间的 次序 将根据下面的 规则 决定:

  • 假设某一天,你访问 i 号房间。
  • 如果算上本次访问,访问 i 号房间的次数为 奇数 ,那么 第二天 需要访问 nextVisit[i] 所指定的房间,其中 0 <= nextVisit[i] <= i 。
  • 如果算上本次访问,访问 i 号房间的次数为 偶数 ,那么 第二天 需要访问 (i + 1) mod n 号房间。

请返回你访问完所有房间的第一天的日期编号。题目数据保证总是存在这样的一天。由于答案可能很大,返回对 109 + 7 取余后的结果。

示例 1:

输入:nextVisit = [0,0]
输出:2
解释:
- 第 0 天,你访问房间 0 。访问 0 号房间的总次数为 1 ,次数为奇数。下一天你需要访问房间的编号是 nextVisit[0] = 0
- 第 1 天,你访问房间 0 。访问 0 号房间的总次数为 2 ,次数为偶数。下一天你需要访问房间的编号是 (0 + 1) mod 2 = 1
- 第 2 天,你访问房间 1 。这是你第一次完成访问所有房间的那天。

示例 2:

输入:nextVisit = [0,0,2]
输出:6
解释:
你每天访问房间的次序是 [0,0,1,0,0,1,2,...] 。
第 6 天是你访问完所有房间的第一天。

示例 3:

输入:nextVisit = [0,1,2,0]
输出:6
解释:
你每天访问房间的次序是 [0,0,1,1,2,2,3,...] 。
第 6 天是你访问完所有房间的第一天。

提示:

  • n == nextVisit.length
  • 2 <= n <= 105
  • 0 <= nextVisit[i] <= i

实现代码与解析:

DP

class Solution {public int firstDayBeenInAllRooms(int[] nextVisit) {int mod = 1000000007;int n = nextVisit.length;long[] f = new long[n];f[0] = 0; // 第一次到达idx0是0,当开始读数据回退的时候才算第一天,所以这里是第0天for (int i = 1; i < n; i++) {int t = nextVisit[i - 1];f[i] = (f[i - 1] + 1 + f[i - 1] - f[t] + 1 + mod) % mod;}return (int)f[n - 1];}
}

原理思路:

        这题,我只能说看着短,但是这题真难想其实,尤其是哪个官解,写的更是让看不懂的更晕了。

        这里的dp[i]数组含义,第一次到第i间房间的天数。 

        所以答案是确定dp[n - 1]。

最主要的是递推式怎么写?

        房间只有偶数次访问才能向前走,所以,当到了第 i 间房间,说明前面的房间一定全部已经访问了偶数次,不然到不了这个房间。(为了书写方便,我用 v 代表nextVisit数组)

        第一次到达i - 1的房间时,一定会消耗一天回溯到  v[ i - 1] 的房间, 令v[i - 1] 为 t(方便书写),因为 i - 1之前的房间一定被访问了偶数次,所以v回溯到 t 房间一定是对其的奇数次访问,在这一时刻,t之前的房间一定也是偶数次访问,t 到 i - 1之间的房间也是偶数次访问,所以我们可以看作为第一次到达 t 房间的状态,我愿称之为重置(但以不是最初的时间,只是状态一致),所以直接用 f[ t ] 表示第一次到达t房间的天数进行后面的计算。

        这时想要第二次到达i - 1这个房间,就需要重新走一遍已经走过的路,用f[ i - 1] - f[ t ] ,即可表示走这段路花费的时间。这时第二次(偶次)到达了i - 1这个房间,再消耗一天,便到了 i 房间。

        这就是递推式f[ i ] 的由来。  f[ i ] = f[i - 1] + 1 + f[i - 1] - f[t] + 1;//注意我两个+1对应粗体字

        我愿称之为,虽然我每接近你一步,轮回的次数就会变多,但是我任然想不断的靠近你,即使每次回溯我都要再花费更长的时间重复经历一遍又一遍。

小细节:

        开long。

        取mod后f[ i - 1] 可能 小于 f [ t ] 所以先 + mod 再 % mod,防止负数出现。

这篇关于LeetCode:1997. 访问完所有房间的第一天(DP Java)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/861950

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory