码上掘金之“寻友之旅”

85 阅读2分钟

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

题目

主题 3:寻友之旅

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

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

分析

看到这道题我最先想到使用动态规划来进行求解,可以使一个数组来存储到达每个节点的时间。显然,每一个最优解必定依赖于其子问题的最优解。对于每一个节点v,我们可以去确定以其为子问题的解,故而得到以下递推公式:

dist[v2]=min(dist[v]+1,dist[v2]);dist[v+1]=min(dist[v]+1,dist[v+1]);dist[v1]=min(dist[v]+1,dist[v1]);dist[v * 2] = min(dist[v] + 1,dist[v * 2]);\newline dist[v + 1] = min(dist[v] + 1,dist[v + 1]);\newline dist[v - 1] = min(dist[v] + 1,dist[v - 1]);\newline

但是,按照如上递推公式,对于每一个节点,需要逐步向下求解其子问题,这与动态规划的思想想矛盾。

进一步思考,我们可以用广度优先搜索的思想来解答,从小青的节点开始搜索,逐步计算至目标节点。对于每个节点,仍然按照如上公式计算下一个节点。这些节点可以使用一个队列进行存储,直至队列中的节点计算完毕。

题解

#include <iostream>
#include <queue>
#include <cstring>
​
using namespace std;
​
const int MAX = 1e5 + 1;
​
int solution(int N, int K){
   if (N >= K){
       // 只能步行
       return N - K;
  }
​
   // 初始化距离数组,-1表示该节点没有被处理
   int dist[MAX];
   memset(dist, -1sizeof(dist));
   //开始节点的距离为0
   dist[N] = 0;
​
   // 待处理结点的队列
   queue<int> q;
​
   // 将开始结点入队
   q.push(N);
   while (!q.empty()){
       int v = q.front();
       q.pop();
​
       if(v * 2 < MAX && dist[v * 2] == -1){//如果节点v*2还没有被处理,将其放入队列中
           dist[v * 2] = dist[v] + 1;
           q.push(v * 2);
      }
       if(v + 1 < MAX && dist[v + 1] == -1){//如果节点v+1还没有被处理,将其放入队列中
           dist[v + 1] = dist[v] + 1;
           q.push(v + 1);
      }
       if(v - 1 >= 0 && dist[v - 1] == -1){//如果节点v-1还没有被处理,将其放入队列中
           dist[v - 1] = dist[v] + 1;
           q.push(v - 1);
      }
  }
   return dist[K];
}
​
int main(){
   int N, K;
   cout << "请输入小青的位置:";
   cin >> N;
   cout << "请输入小码的位置:";
   cin >> K;
   cout << "小青到小码家所需的最短时间为:" << solution(N, K) << "分钟" << endl;
}
​

时间复杂度分析

由于每个节点都需要遍历,故而时间复杂度为:

OnO(n)

总结

我的解法很容易想到。在观看了一众大佬的解法之后,真是大为震撼。比如

yiyiCat大佬提出的位运算解法(有点没太看懂) ,再比如CN千石提出的堆优化的迪杰斯特拉算法。他们的解法我贴在下边:

位运算解法:juejin.cn/post/718807…

堆优化的迪杰斯特拉算法:juejin.cn/post/718138…