当青训营遇上码上掘金。
在本次活动中,我选择的主题为3。
题目
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N,小码在地点 K(0 ≤ N, K ≤ 100000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
求小青从 n 走到 k 的最短时间。
思路
首先我们分析题目,我们能够发现小码不动,于是问题就变成了小青有三种方式移动位置,求最小的变换次数使得小青能够从 n 走到 k。我们再看一眼数据范围,发现如果我们要在 1s 内得出答案,那么这个问题的时间复杂度大致为 O(N) 和 O(NlogN)。
于是我们就能想到是不是有一种方法能够求得小青从 n 出发,到达其它所有点的最短时间呢,那么我们就能想到基于优先队列的 bfs 方法。该方法的原理是每次从优先队列中选出移动次数最少的点,然后用这个点去更新到达其它点的移动次数。那么为什么正确呢?假设我们到达了 x 点,到达该点的移动次数为 y,那么如果 x + 1, x - 1, 2 * x都没有被遍历过,这些点的移动次数就为 y + 1,因为到达 x 已经是最优的,且在优先队列中移动次数是最少的,在优先队列中的其它点的移动次数不会比 y 小,因此这三个点的移动次数最小只能为 y + 1。
通过打标记的方式,我们发现每个点最多只会被遍历一次,所以最后的时间复杂度为 O(n)。
实现
利用 go 标准库中 container/heap 可以完成优先队列的实现。以下为代码链接(code.juejin.cn/pen/7199631…)