“计算从位置 x 到 y 的最少步数”题目解析| 豆包MarsCode AI 刷题

136 阅读3分钟

今天解析AI刷题中的简单题“计算从位置 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

看到这题的第一反应是贪心序列,先增后减,尽量满足1-2-3-4-3-2-1这样走到最大再走回来的序列,然后有些样例会有需要重复的地方。我们首先列出样例的所有情况便于理解:样例1:差值为6,1-2-2-1;样例2:1-2-3-2-2-1;样例3:1-2-3-4-4-3-2-1。可见除了样例3都有重复步数。

介于可以重复步数(下一个数字不仅仅是+1,-1,还可以+0),我就在纠结各种情况,发现并不能有效地分类重复步数的位置和个数(因为下一个数字可以+0,就是可以重复出现过的大的数字,但不能一味地大,还要恰好为目标值)。

随后我参考了文章1文章2,他们均很巧妙地先关注1.2…k-1.k.k-1…2.1=k^2,再根据差值选择重复部分。他们用了枚举和while,但其实通过sqrt函数可以使整个过程很简单,快速得到走到的最大的k。

我们将要补充的数字作为剩余距离m,使用+0重复数字补上。一定有m<(k+1)^2 - k^2=2k+1,不然干脆取k+1,所以m可能取到的最大值是2k,我们确定已有1...k这些共k个数字,2k补两个k即可,所以补的数字最多为2,因为要尽可能地少。

所以当0<m<=k,补一个数即可;当k<m<=2k,补两个数即可。代码如下:

  public static int solution(int xPosition, int yPosition) {
    int distance = Math.abs(xPosition - yPosition);
    int k = (int) Math.floor(Math.sqrt(distance));//floor是向下取整,ceil是向上取整
    if (k * k == distance) {
        return 2 * k - 1;//不补
    }else{
        int left = distance - k*k;
        if(left > k){
            return 2*k+1;//补两个数
        }else{
            return 2*k;//补一个数
        }
    }
}

本题最重要地就是把可重复数字作为剩余距离剥离出来,然后通过平方计算序列之和,约束剩余距离的范围。