LC 1997. 访问完所有房间的第一天
初看这题目觉得似乎有什么公式可以推导出来,但是后来觉得这个公式太复杂以至于没有办法推导出来,因为往回跳的位置其实是不确定的。
这题有好几个关键点:
- 如果某个房间是奇数次访问,那么之前的房间肯定都是偶数次访问过。
- 如果某个房间p是奇数次访问,那么
- 我们需要立刻调回到 next[p] 上
- 然后继续回调若干次,重新回到next[p]上
- 然后前进到next[p]+1上, 此时next[p]+1肯定是奇数
- 接着就和处理next[p]一样
- 所以这里的关键是,如果我们回调到某个位置x(那么此时x一定是奇数次访问),那么重新回到x需要多久,这个可以通过动态规划得到,假设是 `cyc[x]`
- 那么如果访问房间p是奇数次,那么
- 我们回调到 x=next[p] 上,然后重新回到 next[p],就有 cyc[x]+1次跳跃
- 前进到x+1, 然后重新回到 x+1, 就有 cyc[x+1]+1次跳跃
- 直到p-1节点上,最后还有一次跳跃
- 这个过程可以通过前缀和来求解
理清楚了过程代码写起来就比较简单,而且好像也没有什么边界情况。
class Solution: def firstDayBeenInAllRooms(self, nextVisit: List[int]) -> int: n = len(nextVisit) acc = [0] * (n + 1) cyc = [0] * n MOD = 10 ** 9 + 7 for i in range(n): back = nextVisit[i] if back == i: cyc[i] = 1 else: cyc[i] = (acc[i] - acc[back]) + (i - back + 1) cyc[i] %= MOD acc[i + 1] = acc[i] + cyc[i] acc[i + 1] %= MOD # print(cyc) ans = 0 for i in range(n - 1): # how many steps from i to i+1 ans += cyc[i] + 1 ans %= MOD return ans