请帮助小青通知小码,小青最快到达时间是多久? | 码上掘金

117 阅读2分钟

当青训营遇上码上掘金

题目

主题 3:寻友之旅

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

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

作者:青训营官方账号 链接:juejin.cn/post/718775… 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

题目分析

image-20230212165026883.png

如图,绿色的小人是小青,蓝色的小人是小码,0100 000的方向为正方向

通过题目分析可以得出以下结论:

  • 小青的当前位置是地点N,小码的当前位置是地点K

  • 小码不移动,小青可以向前或是向后移动

    • 向前移动

      • 步行

        • 每分钟移动1
      • 公交

        • 每分钟移动N
    • 向后移动

      • 步行

        • 每分钟移动1
  • 小青可能在小码前面

    • 此时,小青只能步行,最短用时N - K
  • 小码在小青前面时

    • 运用贪心法,先坐公交到,不超过地点K,与小码距离最近的位置

      • 此时K - N >= 0, 2 * K - N < 0
    • 判断最后这一段距离是步行快,还是再坐一次公交然后步行返回快

      • 判别式是K - N >= 2 * N - K + 1 ?
      • 如果是步行快,则这一段距离花费K - N
      • 如果再坐一次公交然后步行返回快,则这一段距离花费2 * N - K + 1

参考代码

package main
​
import "fmt"func getTimeMIN(n int, k int) (res int) {
    // 检查数据是否在合法范围内
    if !check(n, k) {
        res = -1
        return
    }
​
    // 判断n是否在k前面
    distance := k - n
    if distance <= 0 {
        res = -distance
        return
    }
​
    // 坐公交到不过k的最近点
    for distance-n > 0 {
        distance -= n
        n <<= 1
        res++
    }
​
    // 判断当前是否已经到k
    // 未达到k则判断是步行快,还是再坐一次公交然后步行返回快
    if distance == 0 {
        return res
    } else {
        if distance >= n-distance+1 {
            res += n - distance + 1
        } else {
            res += distance
        }
    }
    return
}
​
func check(n int, k int) bool {
    if n < 0 || n > 100000 || k < 0 || k > 100000 {
        return false
    }
    return true
}
​
func main() {
    N, K := 2, 100
    res := getTimeMIN(N, K)
    fmt.Printf("当小青在地点%d,小码在地点%d,小青最快到达时间是%d分钟", N, K, res)
}

运行结果:

当小青在地点2,小码在地点100,小青最快到达时间是34分钟

题目总结

  • 总体难度:⭐⭐
  • 身体难度:⭐⭐
  • 编码难度:⭐⭐
  • 题型:简单贪心
  • 新手参考用时:30分钟