[LeetCode] 1997. 访问完所有房间的第一天

 

这题问的很奇怪,其实就是问你什么时候到达最后一个房间,我们所经过的房间都是一点一点增长的,不可能直接跳跃的去到某个房间,而我们到达新房间的唯一途径就是当到达某个房间偶数次时,我们就可以到达下一个新房间,所以说所有的新房间都是一点一点的爬过去的,当你爬完所有的房间至少一遍就是到了访问第n-1个房间。

 这一条件就使得我们访问房间的过程是来回反复的,因为0 <= nextVisit[i] <= i

 比如下面我第一次到达 i 时,它前面的数一定全是偶数次的,因为只有当你访问到了偶数次时才会到达 i 这个位置

[XXXXXXXX]  i

那有人问了我要是访问到了奇数词J会怎么样,此时它就会发生回退,接下来的位置只可能在 J 的前面晃荡,除非我们再通过奇数词规则爬回这个位置

[XXXJXXXX]  i 

 现在我们回到 i ,此时我们到了 i ,但是此时为奇数次,我们发生回退,回退到哪里呢?应该是到nextVisit[ i ]的位置,就看作 j 吧,此时有:(此j非彼J)

[XXX 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值