原文链接: 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 bynextVisit[i]
where0 <= 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
个房间,房间从 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
通过代码
高赞题解
定义状态 $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% |
提交历史
提交时间 | 提交结果 | 执行时间 | 内存消耗 | 语言 |
---|