携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情 >>
访问完所有房间的第一天
你需要访问 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.length2 <= n <= 1050 <= nextVisit[i] <= i
解题思路:
1. 若要到达第 i 个房间,只要到达了两次第 i-1 个房间,便可以使用取模操作并再走一步到达第 i 个房间
2. 第一次到达第 i 个房间是刚好到达 2 次第 i-1 个房间后,使用取模操作再走一步到达的;第二次到达第 i 个房间则是回退到第 next[i] 个房间后,再次尝试到达第 i 个房间
我的答案:
/**
* @param {number[]} nextVisit
* @return {number}
*/
/**
* dp[i]表示到第i个房间时的天数
* nextVisit 只会后退, 那么想要到达第i个房间, 必须是前进到达
* 即必须到达 第i-1个房间 偶数次
* 进而可推出前面所有房间都需到达偶数次(也就是奇数一次 偶数一次)
* 也就是 当前房间次数 = 奇数次 + 偶数次 + 1
* 偶数次 即是 从 nextVisit[i] 再次到达 i
* 需要 dp[i] - dp[nextVisit[i]] + 1 次
* 则 状态转移方程为 dp[i] = dp[i-1] + (dp[i-1] - dp[nextVisit[i]] + 1) + 1
*/
var firstDayBeenInAllRooms = function(nextVisit) {
const mod = 1e9+7
const n = nextVisit.length
const dp = new Array(n)
dp[0] = 0
for(let i = 1; i<n; i++){
dp[i] = (2 * dp[i-1] - dp[nextVisit[i-1]] + 2) % mod
}
return (dp[n-1]+mod) % mod
};
最后
如果有更好的解法或者思路, 欢迎在评论区和我交流~ ღ( ´・ᴗ・` )