当青训营遇上码上掘金
本文是「青训营 X 码上掘金」活动主题3题目 “寻友之旅” 的个人解法。
基于 dp 的做法有很多同学已经发表过了,这里提出一种改进思路:基本的 dp 算法会对 1 - 100000 中的每个位置的最小可达步数进行计算,因此复杂度是 O(N)。但是我认为对所有点进行遍历是过剩的,由于走法只有向前一步、向后一步以及位置 x * 2 三种走法,其中明显乘 2 这种走法效率更高,所以理想的情况下我们只要让路程中乘 2 的操作尽可能多(N >= K 的情况就不用说了吧)。
用 K = 15, N = 3 来举例子,要到达 15 的话,在使用乘 2 的情况下可以从 7 或 8 走两步到达。同样的,7 可以从 3 和 4 两步到达,8 可以从 4 一步到达,也就是说 15 的目标可以从 3 走 4 步到达,也可以从 4 走 3 步到达,因为 N = 3, 所以最优步数为 4。
从这段分析中,可以发现以下规律:
- 对于一个奇数目的地,可以有两种相同开销的走法,但是这两种走法又只会对应到另外两种走法上,即状态不会发散。
- 通过不断对目的地除以 2,最终可以确定出包含 N 值的左界和右界,这时从位置 N 出发可以尝试向这个左界或右界靠拢,计算下此时的最小步数就是最优解。
代码实现如下(点 Script):
在考虑各种条件判断的时候确实思考了一阵,主要的判断点是当前目的地是奇数还是偶数,以及右界包含一个值还是两个值。在查找左右界时复杂度为 O(logn),应该可以比基本的 DP 算法快一些?
不排除有没想到的 bug()。