计算从位置 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
思路
首先处理特殊情况,x和y距离如果是0或1,直接返回
然后模拟情况,如下(orz
| 距离 | 步数变化 | 最小步数 |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 1 | 1 |
| 2 | 1 1 | 2 |
| 3 | 1 1 1 | 3 |
| 4 | 1 2 1 | 3 |
| 5 | 1 2 1 1 | 4 |
| 6 | 1 2 2 1 | 4 |
| 7 | 1 2 2 1 1 | 5 |
| 8 | 1 2 2 2 1 | 5 |
| 9 | 1 2 3 2 1 | 5 |
| 10 | 1 2 3 2 1 1 | 6 |
| ... | ... | ... |
| 13 | 1 2 3 3 2 1 1 | 7 |
| ... | ... | ... |
| 20 | 1 2 3 4 4 3 2 1 | 8 |
暴力
根据规律,其实就是一个等差数列,,所以可以先遍历求出步长最大值a,对于最大步长的预设值,假设刚好是一个回文的字符串,那么最大步长范围为,然后对剩余步数来进行遍历
- 按规律等差数列求和左右两边已走步数
- 剩余步数:,这是就只要考虑剩下步数是直接用最大的步长还是用1来填充
简化
因为这个问题是求出最小步数,可以把问题简化为
- 对于能够用等差数列求和的,步数为
- 根据上面讲述的a和步长和的关系,可以求出剩余步数为,然后就要考虑补充1还是补充a
-
补充a
说明此时剩余步数是a的倍数,补充a的步数为
-
补充1
补充1不补充a说明a不能整除剩余步数,所以此时看余数就是补充1的步数数量
-
def solution(x_position, y_position):
dist = abs(x_position - y_position)
if dist == 0:
return 0
elif dist == 1:
return 1
a = math.isqrt(dist)
cnt = (dist - a * a) // a
if (dist - a * a) % a:
cnt += 1
return cnt + 2 * a - 1
对步长递增取值和递减取值的思考
根据题目要求每步的移动范围是上一步的 -1,+0 或 +1和首末两步的步长必须是 1。求从 x 到 y 的最少步数这两个条件进行模拟,可以看出需要使用等差数列来作为解题的核心。
条件:最小步数步长尽可能的大,所以在移动范围的限制下,递增可以最快的将步数达到需求,同时考虑到最后一步为1,那么最后一步和递增最大点之间应该是0或者-1的关系,可以将0的插入思考全部放在递减部分,那么0怎么插入递减的步数中?选择范围为最大步长到1,如果不使用最大步长a,那么可能剩余的数为之间,这时候0可以插入中间满足要求的数,使取值在的这个数值加上后总步数为x和y的距离