当青训营遇上码上掘金
题目
主题 3:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。 步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1 公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久? 输入: 两个整数 N 和 K 输出: 小青到小码家所需的最短时间(以分钟为单位)
作者:青训营官方账号 链接:juejin.cn/post/718775… 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题目分析
如图,绿色的小人是小青,蓝色的小人是小码,0到100 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分钟