「青训营 X 码上掘金」主题 3:寻友之旅

60 阅读3分钟

当青训营遇上码上掘金

今天解决的是青训营活动中的一道算法题,算法题目如下:

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

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

阅读完这道题之后,我们有了一个大致的思路:可能是考虑使用广搜(BFS)算法对小青的移动进行模拟,计算出最短时间。使用队列维护每个地点的时间,从初始位置开始,每次扩展两种移动方式,直到到达小码的家。最终,取得时间最小的地点即为小青最快到达的时间。

因此,从初始点开始扩展,向两个方向(步行和公交)进行拓展,累加距离,将每一步移动到的新点入队,并且更新该点的距离。当搜到终点时,即可得到最短路径。


const maxUint = ^uint(0)
const maxInt = int(maxUint >> 1)

func shortestTime(N int, K int) int {
    queue := []int{N}
    visited := make([]bool, 100001)
    visited[N] = true
    steps := 0

    for len(queue) > 0 {
        size := len(queue)
        for i := 0; i < size; i++ {
            current := queue[i]
            if current == K {
                return steps
            }
            if current-1 >= 0 && !visited[current-1] {
                queue = append(queue, current-1)
                visited[current-1] = true
            }
            if current+1 <= maxInt && !visited[current+1] {
                queue = append(queue, current+1)
                visited[current+1] = true
            }
            if current*2 <= maxInt && !visited[current*2] {
                queue = append(queue, current*2)
                visited[current*2] = true
            }
        }
        steps++
        queue = queue[size:]
    }
    return -1
}

func main() {
    N := 5
    K := 7
    fmt.Println(shortestTime(N, K))
}

这段代码是一个求小青最快到达小码家的时间的程序,它的思路是使用 BFS 算法对每个节点进行搜索,并将其分为步行和公交两种情况。

  1. 首先声明了两个变量 N 和 K 分别表示小青当前位置和小码位置。
  2. 队列 q 作为 BFS 搜索的队列,并初始化其值为 N 。
  3. 变量 dist 记录小青到达每个节点的时间,初始化为 0 。
  4. 在循环中,对队列的每一个元素进行判断,如果是小码的位置则返回答案,否则进行步行和公交两种情况的搜索。
  5. 步行的情况是当前节点减一或加一,公交情况是当前节点乘二,并将新的节点加入队列。
  6. 如果队列为空,说明没有找到答案,则返回 -1。

整个程序以 BFS 算法为核心,对每个节点进行搜索,找到最快到达小码家的路线,最后返回答案。

以上就是我对于这道题的思路以及答案,如果有更好的思路或者代码可以再次优化的欢迎指点。