AI 刷题 39. 计算位置 x 到 y 的最少步数 题解 | 豆包MarsCode AI刷题

228 阅读3分钟

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

问题描述

给定两个位置 xy,从位置 xy,每一步只能向前走或者向后走,且每一步的步长必须是一个正整数。要求计算从 xy 的最少步数。

思路解析

题目要求第一步必须是 1,并且最后一步也必须是 1。这给我们的解题思路提供了线索:最优的步数安排一定是一个“先上坡再下坡”的过程。

  1. 上坡和下坡的规律

    • 在上下坡的过程中,步长一般是递增的,也就是说从 1 开始,步长逐渐增大,直到某个峰值后开始逐渐减少,直到最后再回到 1
    • 最优的解通常要求步数达到峰值后,再按照一个最小的步长(即 1)返回。
  2. 最优方案

    • 最理想的情况是可以完美地上下坡,不需要中途补充额外的步数。
    • 如果不能完美下坡,就可以通过增加一次适当的步长来弥补差距。特别是当坡顶的步长不够精确地匹配目标位置时,我们可以通过多走一步来补齐剩余的距离。
  3. 如何优化计算

    • 我们将通过枚举不同的峰值来寻找最小步数。每一个峰值的选择都决定了上坡和下坡的速度。
    • 计算每个峰值下,所能走的最大距离,再根据剩余距离来调整。

解题步骤

  1. 计算距离: 首先,我们需要计算从 xy 的距离 dis,即 dis = abs(x_position - y_position)

  2. 枚举峰值: 我们通过一个循环枚举不同的步数峰值 peak。每个 peak 对应一个步长序列,步长从 1 增加到 peak,再从 peak 减少到 1

    • 对于每个峰值 peak,我们首先计算上坡的最大步数(即峰值所对应的距离):
    distance_covered=peak×(peak+1)2distance\_covered = \frac{\text{peak} \times (\text{peak} + 1)}{2}
    • 然后计算剩余的距离 diff = dis - distance_covered
  3. 判断和调整步数

    • 如果剩余的距离 diff 小于 0,说明当前的峰值过大,不可能再增大步长了,返回当前的步数。
    • 如果 diff 大于 0,那么需要补充更多的步数。故计算 diff / peak 来进行判断,如果还有剩余距离,最终需要多走一步。
  4. 更新最小步数: 每次计算完一个峰值对应的步数后,我们都会更新最小步数 result

复杂度分析

  • 时间复杂度O(dis)。枚举峰值的循环次数大约为 dis,因此时间复杂度是 O(dis)
  • 空间复杂度O(1)。整个过程中使用的额外空间是固定的,不依赖于输入规模。

Code

import math;

def solution(x_position, y_position):
    dis = abs(x_position - y_position)  # 计算 x 到 y 的距离
    step_count = 0
    result = 2e9
    
    for peak in range(1, dis): # 枚举步数峰值
        # 等差数列求和:首项为 1, 末项为峰值
        # S = peak(1+peak)/2
        # 2S-peak  为走的步数, 即 peak*peak
        # peak*2-1 为走的次数
        diff = dis - peak*peak
        if(diff < 0): # 如果已经走超了,就代表不可能存在更大的峰值
            return step_count
        step_count = peak*2 - 1
        # 按峰值快步前进
        step_count += int(diff / peak) # 记得强制类型转换,下取整
        diff %= peak
        if(diff != 0):
            # 如果步数不够。则需要补充一步补齐
            step_count += 1
        result = min(step_count, result) # 更新最小步数
    return step_count

if __name__ == "__main__":
    #  You can add more test cases here
    print(solution(12, 6) == 4)
    print(solution(34, 45) == 6)
    print(solution(50, 30) == 8)