第39题 | 豆包MarsCode AI刷题

73 阅读3分钟

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

问题分析

从位置 x 到位置 y,每一步只能向前或向后走,步长为正整数,且满足以下条件:

  1. 第一步和最后一步的步长必须为 1
  2. 步长呈现“先上坡后下坡”的规律,即步长逐步递增到某个峰值后再递减。

目标是找到从 xy 的最少步数。

距离的拆分

假设目标位置与起点的距离为 distance = abs(x - y)

  • 可以通过“先上坡再下坡”形成一个对称的步数分布,最大步长(峰值)设为 peak,则走完上坡和下坡的总距离为: total_distance=peak×peaktotal_distance = peak \times peaktotal_distance=peak×peak
  • 如果 distance > total_distance,需要增加更多的步数来补足差距。

步数计算的三个阶段

  1. 基础步数

    • 从步长 1 递增到 peak,再从 peak递减到 1,总步数为: steps=2×peak−1steps = 2 \times peak - 1steps=2×peak−1
  2. 剩余距离处理

    • 剩余距离为: remaining_distance=distance−total_distanceremaining_distance = distance - total_distanceremaining_distance=distance−total_distance
    • 剩余距离需要通过连续步长为 peak 的步数补齐,步数为: additional_steps=⌊remaining_distance/peak⌋additional_steps = \lfloor remaining_distance / peak \rflooradditional_steps=⌊remaining_distance/peak⌋
    • 如果仍有余数(即 remaining_distance % peak != 0),再增加一步。
  3. 结果更新

    • 每次尝试不同的 peak 值,计算对应的总步数,选择其中最小值。

边界条件

  • 如果 distance = 0,则无需移动,返回 0 步。
  • 如果 distance < 0,由于步长只能是正数,因此不可能存在解。

复杂度分析

  1. 时间复杂度

    • 峰值最多尝试到 distance\sqrt{distance}distance​,复杂度为 O(distance)O(\sqrt{distance})O(distance​)。
  2. 空间复杂度

    • 仅使用了固定变量,复杂度为 O(1)O(1)O(1)。

AI刷题功能亮点

1. 深度解析思路

AI 帮助拆解问题,明确核心规律,例如本题的“先上坡再下坡”模型,快速锁定最优解思路,避免陷入复杂计算。

2. 代码优化指导

在手写代码时,AI 提供逐步伪代码及公式解释,确保逻辑严谨,减少调试时间。例如:

  • 提醒使用 ⌊remaining_distance/peak⌋\lfloor remaining_distance / peak \rfloor⌊remaining_distance/peak⌋ 和取余数判断是否补充步数。
  • 指出峰值的搜索范围应限制到 distance\sqrt{distance}distance​。

3. 个性化刷题强化

通过 AI 提供的类似题目推荐功能,能进一步强化相关知识点的运用,例如动态规划或贪心法,巩固学习。


刷题实践总结

AI 的辅助在以下几个方面表现突出:

  • 节省思考时间
    直接提供核心公式和递推逻辑。
  • 提高学习效率
    提供可执行代码及详细注释,快速验证解法。
  • 增强解题能力
    针对边界条件和复杂度分析提供详细说明,培养全面解题能力。

Java代码实现

public class Main {
    public static int solution(int x_position, int y_position) {
        int distance = Math.abs(x_position - y_position); // 计算 x 到 y 的距离
        if (distance == 0) return 0; // 如果距离为 0,直接返回 0 步

        int result = Integer.MAX_VALUE; // 初始化最小步数为一个较大的值

        for (int peak = 1; peak * peak <= distance; peak++) {
            int coveredDistance = peak * peak; // 峰值所能覆盖的最大距离
            int remainingDistance = distance - coveredDistance; // 剩余距离
            int stepCount = 2 * peak - 1; // 上坡和下坡的基础步数

            if (remainingDistance > 0) {
                // 计算补充步数
                stepCount += remainingDistance / peak; // 整步补齐
                if (remainingDistance % peak != 0) {
                    stepCount++; // 如果还有余数,再补充一步
                }
            }
            result = Math.min(result, stepCount); // 更新最小步数
        }

        return result;
    }

    public static void main(String[] args) {
        // You can add more test cases here
        System.out.println(solution(12, 6) == 4);
        System.out.println(solution(34, 45) == 6);
        System.out.println(solution(50, 30) == 8);
    }
}