计算从位置 x 到 y 的最少步数(类贪心算法)| 豆包MarsCode AI 刷题

89 阅读3分钟

计算从位置 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,即 xy 之间的绝对差值,因为最终的目标是将这个差值缩减到 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 2 3 4 5 5 4 3 2 1

如果diff大于i,在这种情况下,还需要继续移动才能达到目标。需要在已有的步数的中间插入一个步长为 i 的数,并同时再插入一个小于 i 的数,才能完成移动。例如,当 i 为 5 时,剩余的 diff 大于 5,此时可以插入移动步数中间一个步长为 6 的数,并在步序列中插入一个小于 5 的数,这样步数 result 增加 2:

1 2 2 3 4 5 6 5 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);
    }
}