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

37 阅读3分钟

问题描述

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

算法思路

  1. 计算差值:首先计算出xy之间的差值n,如果x大于y,则n为正,否则为负。由于步数与方向无关,所以取绝对值。
  2. 特殊情况处理:如果n为0,即xy相等,那么不需要移动,返回0。
  3. 寻找最小步数:使用一个循环来寻找最小的步数。循环变量i从1开始,表示每一步的大小。m表示当前步长i的连续整数序列的和(即1+3+5+...+(2*i-1))。这个和实际上是一个等差数列的和,其公式为m = i * i
  4. 循环条件:循环直到n小于或等于m,即当前步长i的连续整数序列的和大于或等于xy之间的差值n
  5. 确定步数:如果n大于m - i,说明n不能被m完全覆盖,需要额外一步,所以返回2 * i。否则,n可以被m完全覆盖,但不需要额外的一步,所以返回2 * i - 1

具体步骤

  1. 初始化

    • n 为 xPosition 和 yPosition 的绝对距离。
    • i 初始化为 1,表示第一步。
    • m 初始化为 2,表示第一步所能覆盖的最大距离。
  2. 循环计算

    • 当 n 大于 m 时,继续增加步数 i,并更新 m 为 m + 2 * i
  3. 返回结果

    • 如果 n 大于 m - i,则返回 2 * i
    • 否则返回 2 * i - 1

代码

int solution(int xPosition, int yPosition) {
  int n = xPosition - yPosition;
  if (n == 0)
    return 0;
  if (n < 0)
    n = -n;
  int i = 1;
  long int m = 2 * i;
  while (n > m) {
    i++;
    m = m + 2 * i;
  }
  if (n > m - i)
    return 2 * i;
  else
    return 2 * i - 1;
}

分析时间复杂度

你的代码的时间复杂度主要取决于以下几个部分:

1.计算绝对距离:计算 xPositionyPosition 的绝对距离 n,这一步的时间复杂度是 O(1)。

2.循环部分:循环的目的是找到一个步数 i,使得 m 能够覆盖 n。循环的次数与 n 的大小有关。

3 初始化:初始化 im 的时间复杂度是 O(1)。

4 循环:循环的次数与 n 的大小有关。每次循环中,i 增加 1,m 增加 2 * i。因此,循环的次数大约是 sqrt(n) 次。

5 最坏情况:在最坏情况下,循环的次数大约是 sqrt(n) 次。因此,时间复杂度是 O(sqrt(n))。

因此,整体的时间复杂度是 O(sqrt(n))。

总结

此种形式的解决方式避免了递归,减少了函数调用的开销,将问题简化为寻找合适的步长区间,而不是尝试所有可能的步进组合,从而降低了问题的复杂性。逻辑直观易懂,同时时间复杂度也不太大。