计算从位置 x 到 y 的最少步数
问题描述
小F正在进行一个 AB 实验,需要从整数位置 x 移动到整数位置 y。每一步可以将当前位置增加或减少,且每步的增加或减少的值必须是连续的整数(即每步的移动范围是上一步的 -1,+0 或 +1)。首末两步的步长必须是 1。求从 x 到 y 的最少步数。
输入描述
输入包含两个整数 x 和 y,表示起始位置和目标位置。
输出描述
输出从 x 到 y 所需的最小步数。
测试样例
样例1:
输入:
x_position = 12, y_position = 6
输出:4
样例2:
输入:
x_position = 34, y_position = 45
输出:6
样例3:
输入:
x_position = 50, y_position = 30
输出:8
样例4:
输入:
x_position = 0, y_position = 0
输出:0
问题分析
在刚看到这道题时,我遵循以往的做题经验,先想到了一个暴力的方法,那就是直接宽搜。队列中每次存储的数据为当前的下标,总共走的步数以及上一步走的长度。这样,每次搜索时只需根据上一次走的步长step与当前走到的位置,循环判断step+1+x,step+x与step+x-1是否有到达终点的地方,如果有那就直接返回当前总共走的步数+1即可。我们根据样例1进行操作。(为了方便展示,这里省略了一些数据。)
| 操作轮次 | 当前队列中的元素 | 到达每个地方的最小步数 |
|---|---|---|
| 0 | { (12, 0, 0) } | { 12:0 } |
| 1 | { (11, 1, 1) ... } | { 12:0, 11: 1 ...} |
| 2 | { (10, 2, 1), (9, 2, 2) ... } | { 12:0, ..., 9:2 } |
| 3 | { (8, 3, 1), ... } | {8:3 ... } |
| 4 | { (6, 4, 2), ... } | {6:4, ... } |
当找到目标位置时直接返回其步长即可。但是这种方法有较多弊端,比如如何存储每个位置的最小步数,去除队列中的冗余元素防止一直迭代不到目标位置。但总体来说,这种方法算是问题的一种解决方式。
进一步分析
那有没有一种可以直接求得最终结果得方法呢?我们再来看这个问题,并思考在搜索时的最优路径。显然我们在进行操作时与x和y的初始具体位置并无关系,只需知道他们之间的距离即可。当前问题可以转换为:从0开始,走到|x-y|所需的最小步数。再来思考走法,显然,我们最终走的步长一定是1,2 ... n, n-1, ... 1 这种形式,这也是达到最终目的的最优路径。这里简单计算按照这种走法可以走到的位置。
=
那么,如果是一个完全平方数时,可以直接得到结果为,其中。但如果不是一个完全平方数应该怎么办呢?显然我们可以在这步中再任意添加长度在中的步长。即如果(其中), 时,我们可以用步走到最终的目的地。其实在这里,整个题目已经完成了大部分,只需要注意一点,如果时会怎样?这时候我们可以走两步来达到目的。首先,,原因也很简单,如果,那么,不满足我们的设定。所以,如果时,我们需要走的步数为。
这里给出Python的参考代码。
def solution(x_position, y_position):
dis = abs(x_position - y_position)
n = int(math.sqrt(dis))
if dis == 0: return 0
if n * n == dis: return 2 * n - 1
else: return 2 * n + (1 if dis - n * n > n else 0)
总结
遇到数学问题时,这类题目最怕推公式,我们一但推出具体公式,问题就能迎刃而解。