寻友之旅题解

94 阅读2分钟

当青训营遇上码上掘金

题目:寻友之旅

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

我看到网上要么用dfs,要不用bfs。我觉得可以用二分来做。

第一种情况,N大于等于K,因为观察题目可知,公交只能向后走。一旦小青在小码后面,就只能往前走了。那么我们很容易得出答案是N-K;

第二种情况,N小于K,就开始复杂一点了。但是我们也不难发现,比如啊,小青在n号位置,小码在k号位置(k>n),有没有发现一个细节,假如n在k/2和k之间,那么我们的选择要么就是到k号位置,或者到k/2位置。综合比较下来,到k/2的代价为n-k/2+1(如果k是奇数还得加1),到k的代价就是k-n了。但有人肯定会问,啊,假如n<k/2咋办。那也同理,只不过我们将考虑区间换成了k/4到k/2之间,只是在获得的答案基础上加上了一段公交车的时间。综合看上去,是不是比bfs和dfs更好理解,也省下了更多的空间。

我们只需要全程考虑到k的一半即可,来求出最优解。

PS:笔者没有做大量测试案例,所以说答案可能不完全正确,欢迎评论留言,主要是当我看到一个题解如此错误都在平台上发布我就觉得有必要去做一下。

import java.util.*;

/**
 * @author 滚~韬
 * @date 2023/1/13 15:30
 */
public class Main {
    public static int meet(int n,int k){
        if(n>k){
            return n - k;
        }
        int lastk = k;
        int ans = 0;
        while(n<k){
            if(k%2 == 0){
                k = k/2;
                lastk = k*2;
                ans++;
            }else{
                k = k/2;
                lastk = k*2+1;
                ans++;
            }
        }
        return ans+Math.min(lastk - n - 1, n - k);
    }
    public static void main(String[] args){
        int n = 13;//演示数字
        int k = 39;//演示数字
        System.out.println(meet(n,k));
        scanner.close();
    }

}