寻友之旅| 青训营笔记

113 阅读2分钟

当青训营遇上码上掘金,开寻友之旅。

寻友之旅

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。
小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

题解

看到这道题,首先其实考虑的就是BFS 和动态规划,考虑到这个深度有10万,所以尽可能向动态规划去考虑,此外该题还可以用dijsktra和BFS解决: juejin.cn/post/718837…,同时我验证了我们两个的输出是一样的。

主要思路:

首先,考虑特殊情况,就是如果小青在小码的右边(也就是前面),则只能步行,因为公交乘不能往后走。

其次,我们用 arr 一维数组记录值,arr[x] 表示从N到x的最短时间。在遍历循环的时候,对于 x<Nx < N 的情况 刚刚说过只能走路,因此最短时间就是 NxN-x ,直接可以计算arr数组i0N1arr数组i从0到N-1

在这里还要知道在什么情况下要往回走,肯定是做公交下车往回步行走,如果单纯的走路来回会浪费时间

  • 初始化数组,对于 i==Narr[i]=0;i==N+1,arr[i]=1i==N,arr[i]=0;i==N+1,arr[i]=1

  • 对于 i>N+1i>N+1开始,N>iN -> i的最短路径可以考虑以下情况:(从左边步行走异步过来,从上一站坐车过来,从右边往回走一步)

    • 对于从左边步行走异步过来,就是接着在上个i1i-1时候继续步行 arr[i1]+1arr[i-1]+1
    • 对于从上一站坐车过来,能够坐车必须满足ii为偶数,此外arr[i/2]+1arr[i/2]+1
    • i+1i+1 的时候步行arr[i+1]+1arr[i+1]+1,但是按照我们的遍历规则arr[i+1]arr[i+1]还没轮到记录,因此,我们就要研究arr[i+1]arr[i+1]的上一个状态。如果 arr[i+1]arr[i+1]的值比arr[i1]arr[i-1]的时间还短,说明arr[i+1]arr[i+1]的上一个状态肯定是坐了公交车,于是,能够坐车必须满足i+1i+1为偶数,arr[(i+1)/2]+1+1arr[(i+1)/2]+1 +1
if i == N {
    arr[i] = 0
} else if i == N+1 {
    arr[i] = 1
} else {
    if arr[i] == 0 {
        arr[i] = arr[i-1] + 1
    } else {
        arr[i] = min(arr[i], arr[i-1]+1)
    }
​
    if i%2 == 0 {
        arr[i] = min(arr[i], arr[i/2]+1)
    } else {
        arr[i] = min3(arr[i], arr[i/2]+2, arr[(i+1)/2]+2)
    }
}       

此外,在解决这道题的时候,我又实现了任意两点之间的最短时间,不过对于大数字时间很长。

这是我参与「第五届青训营 」笔记创作活动的第5天.