如何解决计算从位置 x 到 y 的最少步数?
先分析问题描述
小F正在进行一个 AB 实验,需要从整数位置
x
移动到整数位置y
。每一步可以将当前位置增加或减少 ,且每步的增加或减少的值必须是连续的整数 (即每步的移动范围是上一步的-1
,+0
或+1
)。首末两步的步长必须是1
。求从x
到y
的最少步数。
我的思考:打个比方,我生活在一个数轴上,我是小帅,要和小美见面,我们之间有一段距离,去见小美的规则是,从第一步开始就要计算我与小美的距离还有多远,不能把步子走大了 ,减不下速,错过了小美。而我有什么工具能帮助我,及时变速 来确保能够准确的到达小美的位置呢,我们有三个望远镜,第一个望远镜是增距望远镜 ,它可以在我们现走步长基础上加1 去看小美与我们的距离是大于该距离、还是等于该距离、还是小于该距离,第二个望远镜是普通望远镜 ,它可以在我们现走步长基础上保持原有长度 去看小美与我们的距离是大于该距离、还是等于该距离、还是小于该距离,而第三个望远镜是减距望远镜 ,它可以在我们现走步长基础上减1去看小美与我们的距离是大于该距离、还是等于该距离、还是小于该距离,有了这三个工具,我们就能进行更快的判断小美与我们的距离以及我们速度是否足够准确的变速到达她的位置。
那么,有了这三个工具,该如何使用呢?
来看看问题的要求。
来看输入描述
输入包含两个整数
x
和y
,表示起始位置和目标位置。
得先有我和她的位置坐标,计算我们之间的距离,由于距离是正值 ,所以需要用abs函数来去取绝对值。
这是输入情况。
用代码表示一下
js
def solution(x_position, y_position):
# 调用calculate_min_step_size函数,并获取步数计数
step_count = calculate_min_step_size(x_position, y_position)
# 返回步数计数
return step_count`
再看输出描述
输出从
x
到y
所需的最小步数。
既然我们要以最快最高效的方式见到小美,就意味着我们能快则快 ,能增加一,就增加一,当这三个望远镜都还看不到小美的时候,就一直把步长增加一。
而另外的情况,我统一把他们列出来了。
| 情况详细说明 | 增距望远镜 | 普通望远镜 | 减距望远镜 | 怎么走 |
| 是否看见小美 | 远得看不见 | 远得看不见 | 远得看不见 | 步长加1 |
| 是否看见小美 | 刚好看见了 | 远得看不见 | 远得看不见 | 步长加1 |
| 是否看见小美 | 超过小美了 | 远得看不见 | 远得看不见 | 步长不变 |
| 是否看见小美 | 超过小美了 | 刚好看见了 | 远得看不见 | 步长不变 |
| 是否看见小美 | 超过小美了 | 超过小美了 | 远得看不见 | 步长减1 |
| 是否看见小美 | 超过小美了 | 超过小美了 | 刚好看见了 | 步长减1 |
| 是否看见小美 | 超过小美了 | 超过小美了 | 超过小美了 | 刚好遇见你 |
也就是说,我们在尽可能的在最快速度范围内维持一个最大的速度来去奔向小美,确保能够实现用最少的步数来走完我们之间的距离。
OK,思路清晰,开始写代码!
初始步长,计数值,步数值和均为0,原差值就是我们之间距离的作差取绝对值。
js
# 定义calculate_min_step_size函数
def calculate_min_step_size(x_position, y_position):
# 初始化参数
step_size = 0 # 步长
step_count = 0 # 步数计数
step_value_sum = 0 # 步数值和
original_difference = abs(x_position - y_position) # 原差值
然后,就需要把这三个望远镜用公式表达出来。
导入循环。
js
# 循环,直到步数值和等于或超过原差值
while step_value_sum < original_difference:
看看我们之间还有多少距离?
js
计算剩余前进值
remaining_value = original_difference - step_value_sum
第一个望远镜是增距的。所以从步长加1一直逐1递减到1为止。这是一个等差数列,求和用首末项乘项数并除以2来进行计算。
js
increased_steps = (((step_size + 1) + 1) * (step_size + 1)) // 2
第二个望远镜是原有步长保持不变的。所以从步长原有值一直逐1递减到1为止。
js
unchanged_steps = ((step_size + 1) * step_size) // 2
第三个望远镜是减距的。所以从步长减1开始一直逐1递减到1为止。
js
decreased_steps = ((step_size + 1 - 1) * (step_size - 1)) // 2
之后,根据表格中的七种情况,进行大小判断:
js
# 判断条件并执行相应的操作
if increased_steps < remaining_value and unchanged_steps < remaining_value and decreased_steps < remaining_value:
step_size += 1
elif increased_steps == remaining_value and unchanged_steps < remaining_value and decreased_steps < remaining_value:
step_size += 1
elif increased_steps > remaining_value and unchanged_steps < remaining_value and decreased_steps < remaining_value:
step_size = step_size
elif increased_steps > remaining_value and unchanged_steps == remaining_value and decreased_steps < remaining_value:
step_size = step_size
elif increased_steps > remaining_value and unchanged_steps > remaining_value and decreased_steps < remaining_value:
step_size -= 1
elif increased_steps > remaining_value and unchanged_steps > remaining_value and decreased_steps == remaining_value:
step_size -= 1
elif increased_steps > remaining_value and unchanged_steps > remaining_value and decreased_steps > remaining_value:
break
可别忘了在循环结束时,还要更新步数计数和步数值和哦。
bash
# 更新步数计数和步数值和
step_count += 1
step_value_sum += step_size
最后,结束循环后,再返回我们需要的步数计数值,大功告成。
bash
# 返回步数计数
return step_count
可以看看整个流程。
你是否有所收获,我大概是按照这样一个比较普通的判断思路来进行的,哪有还有问题,我积极听取意见并改进。
one more thing
做这道题,我刚开始只想求助AI,结果发现,他们的思路似乎已经陷入瓶颈,无法有所突破,于是我就想通过自己的纸上推演,一点点来去看这样的问题该如何用数学思路解决。
经过一晚上的思考,虽然是个简单题,参照了CSDN里部分同学提供的思路,我发现,这个最少步数的题目,其实最关键的,就是规则。
如果规则要求,增加二,减少二,不变,也许结果又与这种情况有了很大的不同,我知道计算机只能一步一步推理,所以我就把自己当做计算机,一步一步把思路理清楚,才发现,这规则原来是要求我对未来的步长走向进行预判,预判值的大小决定了我对步长下一步设定的变化方向。
这特别像人生,我们从过去的路中,吸取经验,但我们不能就沉浸于过去,而需要往前看未来的趋势,未来会如何变化,我们就要怎样去转变思路,调整自己的方向,每一步都只能改一个步长,是加速,还是减速,亦或者保持原速,都需要根据未来的目标随时调整,这算是一个比较有意思的收获。
而我在思考过程中,使用ai带给我的,其实是一种代码纠错的帮助机制,提供思路的辅助功能,更多的思考还是需要我来去进行,尤其是这里面的思维活动,是ai代替不了的。