当青训营遇上码上掘金——寻友之旅

100 阅读2分钟

当青训营遇上码上掘金

问题

寻友之旅

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

题解

对于该题目采用广度优先搜索的方式来进行解决,同时对于一些特例进行减枝。

首先,由于题目没有提到 N <= K ,所以存在 N > K 的情况,但是公交车只能往前走,所以当 N > K 的时候可以直接返回 N - K。

而对于 N < K 的情况,考虑到如果当前的位置 cur > 2 * K,那么先回退,再坐公交车,比先坐交车再回退能退的更多。而且因为公交车是2倍的关系,所以可以考虑step的长度为K+2;

这么说可能比较难以理解,举个例子 N = 100, K = 198 那么

  1. X-1
  2. 2 * X

即可到达,而

  1. 2 * X
  2. X - 1
  3. X - 1

需要三步才能到达。

所以可以将step设置为K+2来减少step的存储空间。

具体的代码如下所示

import java.util.*;

public class ByteTechCode {

	public int byteTechCode(int N, int K) {
		if(N >= K){
			return N - K;
		}
		int[] dist = new int[K + 2];
		Arrays.fill(dist, -1);
		Queue<Integer> que = new LinkedList<>();
		dist[N] = 0;
		que.add(N);
		while(!que.isEmpty()){
			int u = que.peek();
			if(u == K){
				return dist[K];
			}
			que.poll();
			if(u > 0 && dist[u-1] == -1){
				dist[u-1] = dist[u] + 1;
				que.add(u-1);
			}
			if(u < K && dist[u+1] == -1){
				dist[u+1] = dist[u] + 1;
				que.add(u+1);
			}
			if(2*u < K+2 && dist[2*u] == -1){
				dist[2*u] = dist[u] + 1;
				que.add(2*u);
			}
		}
		return dist[K];
	}
}

class ByteTechCode_test{
	public static void main(String[] args) {
		ByteTechCode test = new ByteTechCode();
		System.out.println(test.byteTechCode(100, 197));
	}
}