day1刷题打卡 | 豆包MarsCode AI刷题

132 阅读3分钟

计算从位置 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

思路

首先处理特殊情况,x和y距离如果是0或1,直接返回

然后模拟情况,如下(orz

距离步数变化最小步数
000
111
21 12
31 1 13
41 2 13
51 2 1 14
61 2 2 14
71 2 2 1 15
81 2 2 2 15
91 2 3 2 15
101 2 3 2 1 16
.........
131 2 3 3 2 1 17
.........
201 2 3 4 4 3 2 18

暴力

根据规律,其实就是一个等差数列,Sn=na1+n(n1)d2S_n=na_1+\frac{n(n-1)d}{2},所以可以先遍历求出步长最大值a,对于最大步长的预设值,假设刚好是一个回文的字符串,那么最大步长范围为a(a+1)a22步长和a \approx \sqrt{\frac{(a+1)a}{2}*2}\approx \sqrt{步长和},然后对剩余步数来进行遍历

  • 按规律等差数列求和左右两边已走步数 a+a(a1)2=a2+a2=a(a+1)2a(a+1)2+a(a1)2a+\frac{a(a-1)}{2} = \frac{a^2+a}{2}=\frac{a(a + 1)}{2}\Rightarrow \frac{a(a+1)}{2}+\frac{a(a-1)}{2}
  • 剩余步数:res=distcntres = dist-cnt,这是就只要考虑剩下步数是直接用最大的步长还是用1来填充

简化

因为这个问题是求出最小步数,可以把问题简化为

  • 对于能够用等差数列求和的,步数为a+(a1)=2a+1a + (a - 1)=2a+1
  • 根据上面讲述的a和步长和的关系,可以求出剩余步数为distaadist-a*a,然后就要考虑补充1还是补充a
    1. 补充a

      说明此时剩余步数是a的倍数,补充a的步数为剩余步数a\frac{剩余步数}{a}

    2. 补充1

      补充1不补充a说明a不能整除剩余步数,所以此时看余数就是补充1的步数数量

def solution(x_position, y_position):
    dist = abs(x_position - y_position)
    if dist == 0:
        return 0
    elif dist == 1:
        return 1
    a = math.isqrt(dist)
    cnt = (dist - a * a) // a
    if (dist - a * a) % a:
        cnt += 1
    return cnt + 2 * a - 1

对步长递增取值和递减取值的思考

根据题目要求每步的移动范围是上一步的 -1+0 或 +1首末两步的步长必须是 1。求从 x 到 y 的最少步数这两个条件进行模拟,可以看出需要使用等差数列来作为解题的核心。

条件:最小步数\rightarrow步长尽可能的大,所以在移动范围的限制下,递增可以最快的将步数达到需求,同时考虑到最后一步为1,那么最后一步和递增最大点之间应该是0或者-1的关系,可以将0的插入思考全部放在递减部分,那么0怎么插入递减的步数中?选择范围为最大步长到1,如果不使用最大步长a,那么可能剩余的数为[1,a1][1,a-1]之间,这时候0可以插入中间满足要求的数,使取值在[1,a1][1,a-1]的这个数值加上后总步数为x和y的距离