题意
小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的距离,那么只需要在某个数继续保持若干步即可,这样的数列之和为,最大保持的可以是2个n,否则就会变为。
如此策略,代码实现逻辑:
-
距离计算:
- 首先计算从位置
x到位置y的绝对距离dis = |x - y|。这是我们需要移动的总距离。
- 首先计算从位置
-
小距离处理:
-
如果
dis小于等于2,则可以直接得出结果。因为在这种情况下,可以用一步或两步完成:- 如果
dis = 0,不需要移动,步数为0。 - 如果
dis = 1,直接移动一步。 - 如果
dis = 2,可以用两步(例如,先移动到中间位置,再移动到目标位置)。
CopyCopy
- 如果
-
-
计算步数:
- 对于更大的
dis,我们需要考虑每一步的移动策略。Copy - 根据题意,首末两步步长必须为
1,中间的步长可以是-1、0或+1,这意味着我们可以在某种程度上调整每一步的增量。
- 对于更大的
-
平方数的应用:
- 通过计算
n = sqrt(dis),可以确定一个最大连续步长n,它表示在n步内,能够覆盖的最大距离为n * n。 - 以
n为步长的序列,我们可以在n步内达到一个位置,然后根据剩余距离调整步数。
- 通过计算
-
剩余距离的处理:
- 计算
dis - n * n,即剩余需要移动的距离。 - 如果剩余距离为
0,那么总步数为2 * (n - 1) + 1(首步1,末步1,中间步数为2 * (n - 1))。 - 如果剩余距离在
1到n之间,则只需再增加一步。 - 如果剩余距离大于
n,则需要再增加两步。
- 计算
-
最终步数计算:
- 根据上述条件判断最终的步数并返回。
代码
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;
}