计算从位置 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
思路
首先计算 diff,即 x 和 y 之间的绝对差值,因为最终的目标是将这个差值缩减到 0。
通过例子不难发现可以通过类似贪心的方式计算从位置 x 到 y 的最少步数,假如输入的diff为11,结果显然为
1 2 3 2 2 1 或者 1 2 2 3 2 1
这表明我们可以先逐步增加步长,然后在靠近目标时逐步减少,最终达到目标位置。因此通过贪心计算的方式,从两端递增计算最小步数长度2 * i,同时diff 减去2 * i,表示进行了一对移动 result + 2。意味着无法再 直到 diff 小于2 * i。意味着无法再进行一对移动。这种方式的关键在于,每次循环都代表着我们在移动过程中选择了一个当前步长 i,并通过两次移动(增加)来缩短与目标位置的差距。
当 diff 小于 2 * i 时,我们便无法再继续以当前步长 i 进行有效的移动。在此时,我们需要根据 diff 的值来判断如何处理剩余的移动:
此时diff如果为0,那么移动完毕。
如果diff小于i,这意味着我们只需要在已有步数中插入一个小于 i 的数便可以完成移动。例如,假设 i 已经递增到 5,此时剩余的 diff 小于 5,只需在步序列中找一个合适的位置(对称)插入一个步长为 2 的移动。这样,步数 result 增加 1:
1 2
23 4 5 5 4 3 2 1
如果diff大于i,在这种情况下,还需要继续移动才能达到目标。需要在已有的步数的中间插入一个步长为 i 的数,并同时再插入一个小于 i 的数,才能完成移动。例如,当 i 为 5 时,剩余的 diff 大于 5,此时可以插入移动步数中间一个步长为 6 的数,并在步序列中插入一个小于 5 的数,这样步数 result 增加 2:
1 2
23 4 565 4 3 2 1
代码
public class Main {
public static int solution(int xPosition, int yPosition) {
int diff = Math.abs(xPosition - yPosition);
if (diff == 1)
return 1;
int i = 1;
int result = 0;
while ((diff - 2 * i) >= 0) {
diff = diff - 2 * i;
result += 2;
i++;
}
if (diff == 0)
return result;
if (diff <= i) {
result += 1;
} else {
result += 2;
}
return result;
}
public static void main(String[] args) {
// You can add more test cases here
System.out.println(solution(12, 6) == 4);
System.out.println(solution(34, 45) == 6);
System.out.println(solution(50, 30) == 8);
}
}