字节跳动青训营主题创作 - 主题 3:寻友之旅 解析

131 阅读1分钟

当青训营遇上码上掘金。今天是 1月13日,距离青训营正式开始还有两天,来做个题热热身。


题目如下:

主题 3:寻友之旅

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

由题意可知,0 <= N < K <= 100000,我们可以先作以下输入输出处理、参数校验:

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    final int N = scanner.nextInt();
    if (outOfRange(N)) return;
    final int K = scanner.nextInt();
    if (outOfRange(K)) return;
    // N(小青)动 K(小码)不动
    final int minutes = handle(N, K);
    System.out.println(minutes);
}

private static boolean outOfRange(int n) {
    return n < 0 || n > 100000;
}

因为小青(以下以N代指),小码(以下以K代指)的初始位置不固定,且 N 存在以下两种移动方式

  1. N = 2 * N,即 y = 2k*x
  2. N = N ± 1,即 y = x ± 1*k

结合分析两种坐标增长模型,不难发现 N 与 K 的坐标可以分为下列两种情况

  • K > 2N
  • N < K < 2N

当 K > 2N 时,N 仅需以坐车方式增长自身路径长度即可 当 N < K < 2N 时,因为当存在中间节点 32N\frac{3}{2}N,所以还需分成下列三种情况考虑

  • K = 32N\frac{3}{2}N
  • K > 32N\frac{3}{2}N
  • K < 32N\frac{3}{2}N

当 K = 中间节点 时,无论是否坐车,都需要行走 32N\frac{3}{2}N-K 的距离
当 K < 中间节点 时,直接步行最佳
当 K > 中间节点 时,应先坐车达 2N 处,再步行至 K 处

代码如下 码上掘金

private static int handle(int N, int K) {
    int minutes = 0;
    while (true) {
        if (N == K) return minutes;
        // N < K <= 2N
        if (N < K && K <= 2*N) {
            final int middle = N / 2 + N;
            // N -> K 距离 <= N/2,步行
            if (K == middle) return minutes + K - N;
            // N -> K 距离 > N/2,步行
            if (middle > K) return minutes + K - N;
            // N -> K 距离 < N/2,坐车+步行
            return minutes + 1 + 2*N-K;
        } else {
            // 坐车
            N = 2*N;
            ++ minutes;
        }
    }
}

验证:输入 N=2 K=100,输出 34

image.png

2^6 + (128-100) = 34,得证