当青训营遇上码上掘金
码上掘金地址:code.juejin.cn/pen/7185528…
题目地址: juejin.cn/post/718775…
题目
-
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
核心代码
// miDistance n为小青位置,k为小码位置,minute为经过的时间
func miDistance(n,k,minute int) int{
if n == k {
return minute
}
if k >= n && ( n * 2 - k <= k - n ) {
minute = miDistance(n * 2, k , minute + 1)
}else {
if k > n {
minute = miDistance(k , k , minute + (k - n))
}else {
minute = miDistance(k , k , minute + (n - k))
}
}
return minute
}
代码讲解
设小青的位置为k,小码的位置为n
小青寻找小码有两种行走方法,一种是2*n跳跃式行走,但不能回头,另一种为n+1逐步式行走,但可以回头,两种方法消耗的代价相同.
可以轻易看出最快的寻找方法就是先跳跃式,到无法靠跳跃式到达的时刻且最近再逐步式寻找.
此时有一个问题,那就是跳跃式到达的时刻哪一个是最近的,是否要跳越过一次小码的位置,是从小码后面向前走近还是从小码前面向走后近,此时必须进行一次判断, n * 2 - k <= k - n,n * 2 为跳跃后的小青位置,n * 2 - k 就是跳跃后小青位置距离小码位置的距离,k - n为跳跃前小青位置距离小码位置的距离,如果跳跃后的距离小于跳跃前的,就必须进行跳跃,才能得到进行的最短时间.
于是有,k >= n && ( n * 2 - k <= k - n ),判断本次行走是否跳跃,如果是就跳跃,否则不进行跳跃.
对于逐步行走,不必进行多次调用,直接加上小青距离小码的距离即可,因为消耗的时间数和行走的距离相同,注意距离为正数