加载中...
1997-访问完所有房间的第一天(First Day Where You Have Been in All the Rooms)
发表于:2021-12-03 | 分类: 中等
字数统计: 1.3k | 阅读时长: 6分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/first-day-where-you-have-been-in-all-the-rooms

英文原文

There are n rooms you need to visit, labeled from 0 to n - 1. Each day is labeled, starting from 0. You will go in and visit one room a day.

Initially on day 0, you visit room 0. The order you visit the rooms for the coming days is determined by the following rules and a given 0-indexed array nextVisit of length n:

  • Assuming that on a day, you visit room i,
  • if you have been in room i an odd number of times (including the current visit), on the next day you will visit a room with a lower or equal room number specified by nextVisit[i] where 0 <= nextVisit[i] <= i;
  • if you have been in room i an even number of times (including the current visit), on the next day you will visit room (i + 1) mod n.

Return the label of the first day where you have been in all the rooms. It can be shown that such a day exists. Since the answer may be very large, return it modulo 109 + 7.

 

Example 1:

Input: nextVisit = [0,0]
Output: 2
Explanation:
- On day 0, you visit room 0. The total times you have been in room 0 is 1, which is odd.
  On the next day you will visit room nextVisit[0] = 0
- On day 1, you visit room 0, The total times you have been in room 0 is 2, which is even.
  On the next day you will visit room (0 + 1) mod 2 = 1
- On day 2, you visit room 1. This is the first day where you have been in all the rooms.

Example 2:

Input: nextVisit = [0,0,2]
Output: 6
Explanation:
Your room visiting order for each day is: [0,0,1,0,0,1,2,...].
Day 6 is the first day where you have been in all the rooms.

Example 3:

Input: nextVisit = [0,1,2,0]
Output: 6
Explanation:
Your room visiting order for each day is: [0,0,1,1,2,2,3,...].
Day 6 is the first day where you have been in all the rooms.

 

Constraints:

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

中文题目

你需要访问 n 个房间,房间从 0n - 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

通过代码

高赞题解

定义状态 $f[i]$ 表示从首次访问房间 $i$ 到访问房间 $i+1$ 之前所需要的天数。

根据题意,首次访问房间 $i$ 时,下一天是一定要回到 $j=\textit{nextVisit}[i]$ 房间的,下文简称为「回访」。如果从房间 $i$ 回访到房间 $j$,此时 $[j,i-1]$ 范围内的房间必然都处于访问过偶数次的状态,这意味着从 $j$ 到 $i$ 的过程中,我们需要回访 $[j,i-1]$ 范围内的每个房间。加上访问房间 $i$ 的 $2$ 天,于是有转移方程:

$$
f[i] = 2 + \sum_{k=j}^{i-1} f[k]
$$

其中和式可以用前缀和优化,这样单次转移就是 $O(1)$ 的。

代码实现时,可以略去数组 $f$,直接将其记录在前缀和 $\textit{sum}$ 中。

最后还需要加上访问第 $n-1$ 号房间的 $1$ 天开销,但由于天数是从 $0$ 开始的,答案需要减 $1$,所以最后答案为 $\textit{sum}[n-1]+1-1=\textit{sum}[n-1]$。

func firstDayBeenInAllRooms(nextVisit []int) int {
	const mod int = 1e9 + 7
	n := len(nextVisit)
	sum := make([]int, n)
	for i, j := range nextVisit[:n-1] { // 不用考虑最后一天
		f := (2 + sum[i] - sum[j] + mod) % mod // +mod 是为了防止出现负数
		sum[i+1] = (sum[i] + f) % mod
	}
	return sum[n-1]
}

统计信息

通过次数 提交次数 AC比率
2232 6568 34.0%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
1996-游戏中弱角色的数量(The Number of Weak Characters in the Game)
下一篇:
2000-反转单词前缀(Reverse Prefix of Word)
本文目录
本文目录