青训营-计算位置x到y的最少步数

245 阅读4分钟

计算位置x到y的最少步数

AB 实验同学每天都很苦恼如何可以更好地进行 AB 实验,每一步的流程很重要,我们目标为了缩短所需的步数。

我们假设每一步对应到每一个位置。从一个整数位置 x 走到另外一个整数位置 y,每一步的长度是正整数,每步的值等于上一步的值 -1+0+1。求 xy 最少走几步。并且第一步必须是 1,最后一步必须是 1,从 xy 最少需要多少步。

样例说明

  • 整数位置 x12,另外一个整数位置 y6,我们需要从 x 走到 y,最小的步数为:1221,所以我们需要走 4 步。
  • 整数位置 x34,另外一个整数位置 y45,我们需要从 x 走到 y,最小的步数为:123221,所以我们需要走 6 步。
  • 整数位置 x50,另外一个整数位置 y30,我们需要从 x 走到 y,最小的步数为:12344321,所以我们需要走 8 步。

输入格式

输入包含 2 个整数 xy。(0<=x<=y<2^31

输出格式

对于每一组数据,输出一行,仅包含一个整数,从 xy 所需最小步数。

输入样例

12 6
34 45
50 30

输出样例

4
6
8

解题思路!!!非原创(一点小地方做了改动,方便自己理解,所以写个文章,不一定正确)

要解决这个问题,我们需要理解步长变化规则,并设计一种策略,既能快速覆盖距离,又能满足步长变化的限制。一下是详细的思路分析。

1.距离计算

首先,计算总距离 diff=|y-x|

2.步长变化规则

.起始步长: 第一步必须是1

.步长变化: 每一步的步长等于上一步的值 -1+0+1

.结束步长: 最后一步必须是1

3.步长序列的特性

为了最小化步数,我们希望步长尽可能地快速增加,以覆盖更多的距离,然后再逐步减少步长,以满足最后一步必须为1的条件。这类似于形成一个“山峰”形状的步长序列。

4. 最大步长k的确定

假设步长序列的最大步长为k,那么序列大致会是1, 2, 3, ..., k, ..., 3, 2, 1。需要确定k的值,使得步长序列的总和尽可能接近但不超过diff
为了估算k,我们可以利用数学中的等差数列求和公式:

S= 1 + 2 + 3 + ··· + k = k(k + 1)/2

这个公式表示步长从1增加到k时的总距离。如果我们希望总距离接近diff,则可以近似认为: k^2 == diff, 因此,k的值可以通过计算k = sqrt(diff)来估算。

5. 计算最少步数

根据最大步长k,最少步数可以通过以下公式计算:

  • 如果k^2 < diff
    这里的情况是
    1 + 2 + 3 + ··· + k + k-1 + k-2 + ··· + 2 + 1 < diff

    1 + 2 + 3 + ··· + k + k+1 + k + k-1 + ··· + 2 + 1 > diff
    范围是 1 到 2k,对应 1 到 2 个数,这些数可以是 1 到 k 中的任意数,只要满足最后的序列相加等于diff。

    • 需要额外的步数来覆盖剩余的距离diff - k^2
    • 额外步数
    • 补充 最多+2步
    • (k+1)^2-k^2=2k+1 距离都为整数,则额外步数最多为2k,需要两步
    • 即:当(diff-k^2)<=kextraSteps=1 else extraSteps=2;
    • 总步数n = 2k - 1 + extraSteps
  • 否则

    • 总步数n = 2k - 1

6. 特殊情况处理

  • diff = 0:起点和终点相同,不需要任何步数,n = 0

算法实现

#include <iostream>
#include<cmath>
int solution(int x, int y) {
    // Please write your code here
  int minSteps;
  if(x>y)
  {int temp=x;
  x=y;
  y=temp;
  }
  int diff=y-x;
  if(diff==0) return 0;
 int  k=(int)sqrt(diff);
 int  KSqared =k*k;
 int distance=diff-KSqared;
 if(distance!=0)
 {
    if(distance<=k)    return 2*k;
    else return 2*k+1;
 }
 else return 2*k-1; 
  
  
}

int main() {
    //  You can add more test cases here
    std::cout << (solution(12, 6) == 4) << std::endl;
    std::cout << (solution(34, 45) == 6) << std::endl;
    std::cout << (solution(50, 30) == 8) << std::endl;
    return 0;
}

原创作者:热的棒打鲜橙
链接:juejin.cn/post/742025…