「青训营 X 码上掘金」寻友之旅

58 阅读2分钟

当青训营遇上码上掘金

主题三 - 寻友之旅

题目描述:

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。

  • 步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
  • 公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久?

输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

思路:

这个问题可以再抽象一下,把一分钟看作是走一步,移动节点的长度看成一步迈出去的步长,那么这道题就变成了求小青到小码的最短步数,这样看是不是想到了经典的 BFS 模型,广度优先搜索逐层扩展,扩展次数就是最短步数,直接把 BFS 模板搬过来就搞定了。

宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。

Java 代码:

import java.util.LinkedList;
import java.util.Queue;

public class Solution {

    final static int MAX_LEN = (int) 1e5;

    static class Node {
        int position;
        int step;

        Node(int position, int step) {
            this.position = position;
            this.step = step;
        }
    }

    public int bfs(int n, int k) {
        if (n == k) return 0;
        Queue<Node> que = new LinkedList<>();
        que.add(new Node(n, 0));
        while (!que.isEmpty()) {
            Node curr_node = que.poll();
            if (curr_node.position == k)
                return curr_node.step;
            if (curr_node.position + 1 <= MAX_LEN)
                que.add(new Node(curr_node.position + 1, curr_node.step + 1));
            if (curr_node.position - 1 <= MAX_LEN)
                que.add(new Node(curr_node.position - 1, curr_node.step + 1));
            if (curr_node.position * 2 <= MAX_LEN)
                que.add(new Node(curr_node.position * 2, curr_node.step + 1));
        }
        return -1;
    }
}

Node 节点用来存储小青当前的位置以及走的步数(分钟),先将初始位置加入队列,只要队列不为空,就取队首元素向 +1,-1,*2 这三个位置扩展,直到遇到小码。