当青训营遇上码上掘金。今天是 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 存在以下两种移动方式
- N = 2 * N,即 y = 2k*x
- N = N ± 1,即 y = x ± 1*k
结合分析两种坐标增长模型,不难发现 N 与 K 的坐标可以分为下列两种情况
- K > 2N
- N < K < 2N
当 K > 2N 时,N 仅需以坐车方式增长自身路径长度即可 当 N < K < 2N 时,因为当存在中间节点 ,所以还需分成下列三种情况考虑
- K =
- K >
- K <
当 K = 中间节点 时,无论是否坐车,都需要行走 -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
2^6 + (128-100) = 34,得证