题解39. 计算从位置 x 到 y 的最少步数 | 豆包MarsCode AI刷题

42 阅读2分钟

题意

小F正在进行一个 AB 实验,需要从整数位置 x 移动到整数位置 y。每一步可以将当前位置增加或减少,且每步的增加或减少的值必须是连续的整数(即每步的移动范围是上一步的 -1+0 或 +1)。首末两步的步长必须是 1。求从 x 到 y 的最少步数。

思路分析

首先明确的一点是,答案只与x和y的相对差值有关,而与两者的绝对大小无关。

按照贪心来看,最优的策略是一直递增步长,即“1、2、3...”,但是要求最后的一步必须是1,那么可以想到,应当是慢慢递增到一个合适的最大步长,再从最大步长慢慢递减回1,这样是最优的。

进一步考虑,这样的序列“1, 2, 3, ..., n-1, n, n-1, ..., 3, 2, 1”,不一定就完全等于x和y的距离,那么只需要在某个数继续保持若干步即可,这样的数列之和为n2n^2,最大保持的可以是2个n,否则就会变为n2+2n=(n+1)2n^2+2n=(n+1)^2

如此策略,代码实现逻辑:

  1. 距离计算

    • 首先计算从位置 x 到位置 y 的绝对距离 dis = |x - y|。这是我们需要移动的总距离。
  2. 小距离处理

    • 如果 dis 小于等于 2,则可以直接得出结果。因为在这种情况下,可以用一步或两步完成:

      • 如果 dis = 0,不需要移动,步数为 0
      • 如果 dis = 1,直接移动一步。
      • 如果 dis = 2,可以用两步(例如,先移动到中间位置,再移动到目标位置)。

      CopyCopy

  3. 计算步数

    • 对于更大的 dis,我们需要考虑每一步的移动策略。Copy
    • 根据题意,首末两步步长必须为 1,中间的步长可以是 -10 或 +1,这意味着我们可以在某种程度上调整每一步的增量。
  4. 平方数的应用

    • 通过计算 n = sqrt(dis),可以确定一个最大连续步长 n,它表示在 n 步内,能够覆盖的最大距离为 n * n
    • 以 n 为步长的序列,我们可以在 n 步内达到一个位置,然后根据剩余距离调整步数。
  5. 剩余距离的处理

    • 计算 dis - n * n,即剩余需要移动的距离。
    • 如果剩余距离为 0,那么总步数为 2 * (n - 1) + 1(首步 1,末步 1,中间步数为 2 * (n - 1))。
    • 如果剩余距离在 1 到 n 之间,则只需再增加一步。
    • 如果剩余距离大于 n,则需要再增加两步。
  6. 最终步数计算

    • 根据上述条件判断最终的步数并返回。

代码

int solution(int xPosition, int yPosition) {
    // Please write your code here
    int dis = abs(xPosition - yPosition);
    if (dis <= 2) {
        return dis;
    }
    int ans;
    int n = sqrt(dis);
    ans = (n-1) << 1;
    ans++;
    dis -= n * n;
    if (dis) {
        if (dis <= n) {
            ans++;
        } else {
            ans += 2;
        }
    }
    return ans;
}