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的距离

相关推荐
滑滑滑2 天前
后端实践-优化一个已有的 Go 程序提高其性能 | 豆包MarsCode AI刷题
青训营笔记
柠檬柠檬2 天前
Go 语言入门指南:基础语法和常用特性解析 | 豆包MarsCode AI刷题
青训营笔记
用户967136399652 天前
计算最小步长丨豆包MarsCodeAI刷题
青训营笔记
用户52975799354723 天前
字节跳动青训营刷题笔记2| 豆包MarsCode AI刷题
青训营笔记
clearcold3 天前
浅谈对LangChain中Model I/O的见解 | 豆包MarsCode AI刷题
青训营笔记
夭要7夜宵3 天前
【字节青训营】 Go 进阶语言:并发概述、Goroutine、Channel、协程池 | 豆包MarsCode AI刷题
青训营笔记
用户336901104444 天前
数字分组求和题解 | 豆包MarsCode AI刷题
青训营笔记
dnxb1234 天前
GO语言工程实践课后作业:实现思路、代码以及路径记录 | 豆包MarsCode AI刷题
青训营笔记
用户916357440954 天前
AI刷题-动态规划“DNA序列编辑距离” | 豆包MarsCode AI刷题
青训营笔记
热的棒打鲜橙4 天前
数字分组求偶数和 | 豆包MarsCode AI刷题
青训营笔记