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

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

问题描述

小F正在进行一个 AB 实验,需要从整数位置 x 移动到整数位置 y。每一步可以将当前位置增加或减少,且每步的增加或减少的值必须是连续的整数(即每步的移动范围是上一步的 -1+0+1)。首末两步的步长必须是 1。求从 xy 的最少步数。

输入描述

输入包含两个整数 xy,表示起始位置和目标位置。

输出描述

输出从 xy 所需的最小步数。


测试样例

样例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

距离 步数变化 最小步数
0 0 0
1 1 1
2 1 1 2
3 1 1 1 3
4 1 2 1 3
5 1 2 1 1 4
6 1 2 2 1 4
7 1 2 2 1 1 5
8 1 2 2 2 1 5
9 1 2 3 2 1 5
10 1 2 3 2 1 1 6
... ... ...
13 1 2 3 3 2 1 1 7
... ... ...
20 1 2 3 4 4 3 2 1 8

暴力

根据规律,其实就是一个等差数列, <math xmlns="http://www.w3.org/1998/Math/MathML"> S n = n a 1 + n ( n − 1 ) d 2 S_n=na_1+\frac{n(n-1)d}{2} </math>Sn=na1+2n(n−1)d,所以可以先遍历求出步长最大值a,对于最大步长的预设值,假设刚好是一个回文的字符串,那么最大步长范围为 <math xmlns="http://www.w3.org/1998/Math/MathML"> a ≈ ( a + 1 ) a 2 ∗ 2 ≈ 步长和 a \approx \sqrt{\frac{(a+1)a}{2}*2}\approx \sqrt{步长和} </math>a≈2(a+1)a∗2 ≈步长和 ,然后对剩余步数来进行遍历

  • 按规律等差数列求和左右两边已走步数 <math xmlns="http://www.w3.org/1998/Math/MathML"> a + a ( a − 1 ) 2 = a 2 + a 2 = a ( a + 1 ) 2 ⇒ a ( a + 1 ) 2 + a ( a − 1 ) 2 a+\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} </math>a+2a(a−1)=2a2+a=2a(a+1)⇒2a(a+1)+2a(a−1)
  • 剩余步数: <math xmlns="http://www.w3.org/1998/Math/MathML"> r e s = d i s t − c n t res = dist-cnt </math>res=dist−cnt,这是就只要考虑剩下步数是直接用最大的步长还是用1来填充

简化

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

  • 对于能够用等差数列求和的,步数为 <math xmlns="http://www.w3.org/1998/Math/MathML"> a + ( a − 1 ) = 2 a + 1 a + (a - 1)=2a+1 </math>a+(a−1)=2a+1
  • 根据上面讲述的a和步长和的关系,可以求出剩余步数为 <math xmlns="http://www.w3.org/1998/Math/MathML"> d i s t − a ∗ a dist-a*a </math>dist−a∗a,然后就要考虑补充1还是补充a
    1. 补充a

      说明此时剩余步数是a的倍数,补充a的步数为 <math xmlns="http://www.w3.org/1998/Math/MathML"> 剩余步数 a \frac{剩余步数}{a} </math>a剩余步数

    2. 补充1

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

python 复制代码
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。求从 xy 的最少步数这两个条件进行模拟,可以看出需要使用等差数列来作为解题的核心。

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

相关推荐
tabzzz16 小时前
突破Zustand的局限性:与React ContentAPI搭配使用
前端·青训营笔记
Serendipity5652 天前
Go 语言入门指南——单元测试 | 豆包MarsCode AI刷题;
青训营笔记
wml4 天前
前端实践-使用React实现简单代办事项列表 | 豆包MarsCode AI刷题
青训营笔记
用户44710308932425 天前
详解前端框架中的设计模式 | 豆包MarsCode AI刷题
青训营笔记
用户5836838006765 天前
学习笔记22《易速鲜花聊天客服机器人的开发(上)》
青训营笔记
用户285620017135 天前
寻找观光景点组合的最高得分| 豆包MarsCode AI 刷题
青训营笔记
用户48486281292226 天前
LangChain启程篇 | 豆包MarsCode AI刷题
青训营笔记
用户1538734266806 天前
前端框架中的设计模式解析
青训营笔记
努力的小Qin8 天前
小T的密码变换规则(青训营X豆包MarsCode) | 豆包MarsCode AI 刷题
青训营笔记
liangxiu8 天前
CSS布局技巧汇总| 豆包MarsCode AI刷题
青训营笔记