寻友之旅 |「青训营 X 码上掘金」主题创作

85 阅读1分钟

题目描述

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

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

思路分析

n, k的数据范围为[0,105][0, 10^5], 则算法复杂度应该控制在O(nlogn)O(n\log{n})时间以下。

  1. 小青向后走的方法只能通过步行, 则当knk \leq n 时, 时间为两点间距离。
  2. 贪心的考虑下, 一直坐公交一定是最优的, 当到达最近距离时, 步行完成。
  3. 每个点只会存在三条路线, 1,1,2{-1, 1, \ast 2}, 于是可以采用搜索的方式, 剪枝掉不合理的情况。
  4. 从终点考虑, 到达终点的方式只有1,1,2{-1, 1, \ast 2}三种, 而到达这些点的方式同样三种, 于是有了动态规划
dpi={dpi1+1,dpi+1+1,dpi/2+1,i%2==0dp(i1)/2+2,ifi%2==1dp_i= \begin{cases} dp_{i - 1} + 1, & \\ dp_{i + 1} + 1, & \\ dp_{i / 2} + 1, & i \% 2 == 0 \\ dp_{(i - 1) / 2} + 2, & if i \% 2 == 1 \end{cases}

代码

贪心

class Solution {
    int getDistance(int n, int k) {
        int res = abs(n - k);
        if (n >= k) return res;
        
        while (2 * n <= k) {
            res = min(res, abs(2 * n - k));
            n *= 2;
        }
        return res;
    }
}

搜索 - BFS

class Solution {
    int getDistance(int n, int k) {
        if (n >= k) return n - k;
        
        queue<pair<int, int>> q;
        q.push({n, 0});
        
        while (q.size()) {
            auto t = q.front();
            q.pop();
            
            if (t.first == k) return t.second;
            if (t.first < k) {
                q.push({t.first + 1, t.second + 1});
                q.push({t.first * 2, t.second + 1});
            }
            else q.push({t.first - 1, t.second + 1});
        }
    }
}

动态规划

class Solution {
    int getDistance(int n, int k) {
        if (n >= k) return n - k;
        
        vector<int> dp(k + 1, 1e9);
        dp[n] = 0;
        for (int i = n + 1; i <= k; i ++ ) {
            dp[i] = min(dp[i], min(dp[i - 1], dp[i + 1]) + 1);
            if (i % 2 == 0) {
                dp[i] = min(dp[i], dp[i >> 1] + 1);
            }
            else {
                dp[i] = min(dp[i], dp[(i - 1) >> 1] + 1);
            }
        }
        return dp[k];
    }
}