题目描述
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
思路分析
n, k的数据范围为, 则算法复杂度应该控制在时间以下。
- 小青向后走的方法只能通过步行, 则当时, 时间为两点间距离。
- 贪心的考虑下, 一直坐公交一定是最优的, 当到达最近距离时, 步行完成。
- 每个点只会存在三条路线, , 于是可以采用搜索的方式, 剪枝掉不合理的情况。
- 从终点考虑, 到达终点的方式只有三种, 而到达这些点的方式同样三种, 于是有了动态规划。
代码
贪心
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];
}
}