当青训营遇上码上掘金-寻友之旅-但不能帮我找到另一半

62 阅读2分钟

这是我在掘金的第一个文章,写得不好还请见谅。

首先来看青训营的第三个题目:

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

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

首先我们可以简化题目,就是从一个点到另一个点的最短移动距离,且只能通过向前1步、向后1步、或移动两倍的部署三种来移动,因此我们可以再简化成一个一维数组来表述运动的路径和状态。

再看,题目求的是最快到达时间,也就是说是求最短距离,分析一下,有最短距离就肯定不存在环路,在一维数组的理解就是只能经过这个格子一次,也就是除了初始化最多只能存放一次数据;同时,也就意味着,只要第一次得到的结果与终点相同,则说明至少当前就是一个最优解。

分析一下,我们可以发现,通过使用队列来存放当前的位置的同时,也可以间接的记录了步数,因为只要不是终点,就会被插入队列,相当于步数会一步一步的不断上升,通过队列和BFS的思想便可以实现本题目的要求。因此本题的考点便时使用队列完成BFS的搜索。

梳理完上面的思路,接下来就是实现代码了。

import java.util.*;

public class test {
    static int n;
    static int k;
    static final int N = 100010;

    private static int bfs() {
        int[] dist = new int[N];
        Queue<Integer> queue = new LinkedList<>();
        Arrays.fill(dist, -1);
        queue.add(n);
        dist[n] = 0;
        while (!queue.isEmpty()) {
            int t = queue.poll();
            if (t - 1 >= 0 && dist[t - 1] == -1) {
                dist[t - 1] = dist[t] + 1;
                if (t - 1 == k) return dist[t - 1];
                queue.add(t - 1);
            }
            if (t + 1 >= 0 && dist[t + 1] == -1) {
                dist[t + 1] = dist[t] + 1;
                if (t + 1 == k) return dist[t + 1];
                queue.add(t + 1);
            }
            if (t * 2 < N && dist[t * 2] == -1) {
                dist[t * 2] = dist[t] + 1;
                if (t * 2 == k) return dist[t * 2];
                queue.add(t * 2);
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        k = sc.nextInt();
        System.out.println(bfs());
    }
}

就这样,小青就走过了一个寻友之旅到达了小码家,但是我借鉴了小青的寻友之旅还是找不到另一半……