这题问的很奇怪,其实就是问你什么时候到达最后一个房间,我们所经过的房间都是一点一点增长的,不可能直接跳跃的去到某个房间,而我们到达新房间的唯一途径就是当到达某个房间偶数次时,我们就可以到达下一个新房间,所以说所有的新房间都是一点一点的爬过去的,当你爬完所有的房间至少一遍就是到了访问第n-1个房间。
这一条件就使得我们访问房间的过程是来回反复的,因为0 <= nextVisit[i] <= i
比如下面我第一次到达 i 时,它前面的数一定全是偶数次的,因为只有当你访问到了偶数次时才会到达 i 这个位置
[XXXXXXXX] i
那有人问了我要是访问到了奇数词J会怎么样,此时它就会发生回退,接下来的位置只可能在 J 的前面晃荡,除非我们再通过奇数词规则爬回这个位置
[XXXJXXXX] i
现在我们回到 i ,此时我们到了 i ,但是此时为奇数次,我们发生回退,回退到哪里呢?应该是到nextVisit[ i ]的位置,就看作 j 吧,此时有:(此j非彼J)
[XXX j XXXX] i
此时我们发现,这就和我们第一次到达j的情况一模一样,同时j的前面访问了偶数次,后面也访问了偶数次(就相当于零次),说明我们需要重新走一遍从j到i的历史。
我们定义一个dp[ i ]用于表示第一次到达i的时间,所以历史从j到i需要dp[ i ]-dp[ j ]天,同时需要加上从i到j的1天(此时已经刚刚到j)
所以我们有:
dp[ i+1 ]=dp[ i ]+1+(dp[ i ]-dp[ j ])+1
理解到这里我们思路就很清晰了,下面是我写的代码(可能不是最优):
class Solution(object):
def firstDayBeenInAllRooms(self, nextVisit):
dp=[0 for k in range(100005)]
M=10**9+7
n=len(nextVisit)
room=[0 for j in range(n-1)]
for i in range(n):
j=nextVisit[i]
dp[i+1]=(dp[i]+1+(dp[i]-dp[j])+M)%M+1
return dp[n-1]%M