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

155 阅读2分钟

当青训营遇上码上掘金

题目

主题 3:寻友之旅

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

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

作者:青训营官方账号
链接:juejin.cn/post/718775…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解法

Dijkstra

可将整条直线抽象为有向无环图,对于图上的节点X,存在X-1、X+1、X*2这三个临接节点,距离为1。

对于起始点,距离最近且未访问过的顶点即为它的所有邻接节点(距离都为1),第1次,我们遍历它们,第2次我们依次遍历它们未访问过的临接节点,再将这些临接节点的临接节点加入下一次遍历的节点中,对于第i次要遍历的节点,距离为i,也是距离最近且未访问过的顶点(小于i的节点都已遍历过),直到扩展到终点为止,此时到达终点的距离即为最小距离。

定义节点:

class node_dst
{
public:
    int node;
    int dst;
    node_dst(int a, int b)
    {
        node = a;
        dst = b;
    }
    void print()
    {
        cout << "node: " << node << "\tdst: " << dst << endl;
    }
};

算法:

这里用到集合来存储已经遍历过的节点

这里用到队列,从队头取出当前遍历的节点,再将该节点的临接节点加入到队列末尾。 添加之前需要对范围做校验,还要校验其不在集合内(未遍历过)

int findFriend(int n, int k)
{
    if (n < 0 || k > 10e5)
    {
        cout << "invalid input!" << endl;
        return -1;
    }
    if (n >= k)
    {
        return n - k;
    }
    queue<node_dst> q;
    node_dst start(n, 0);
    set<int> has;
    int ans;
    q.push(start);
    has.insert(n);
    while (!q.empty())
    {
        node_dst recent = q.front();
        recent.print();
        if (recent.node == k)
        {
            ans = recent.dst;
            break;
        }
        q.pop();
        if (recent.node + 1 <= 10e5 && has.find(recent.node + 1) == has.end())
        {
            has.insert(recent.node + 1);
            node_dst temp(recent.node + 1, recent.dst + 1);
            q.push(temp);
        }
        if (recent.node - 1 < 0 && has.find(recent.node - 1) == has.end())
        {
            has.insert(recent.node - 1);
            node_dst temp(recent.node - 1, recent.dst + 1);
            q.push(temp);
        }
        if (recent.node * 2 <= 10e5 && has.find(recent.node * 2) == has.end())
        {
            has.insert(recent.node * 2);
            node_dst temp(recent.node * 2, recent.dst + 1);
            q.push(temp);
        }
    }
    return ans;
}