1、简单1/10:计算位置 x 到 y 的最少步数
文章目录
疑问:为什么对称就是最优解。这是一个固定答案吗(是的)
理解:由于加速是最快的,减速也是最快的,规定步长为1,则为均加速及匀减速。想象半圆形。想象物理上公式Y=a+bx^2,如果初始条件不一致则会有多个不同答案,故限制初始步数为1.同时由于最后一步也是1,则为对称。
图形学理解:
感谢伊希尔老师的解惑,用图形来理解就很快了。(据她说这也是变相的:最快降速法)
故本题目:在于理解的整体的解题方法(即理解为什么对称就是最优解),才能得到 用2整除的步数思路,同时用2整除也是两边总部署对称,故只有在偶数倍时候重复计算距离,而不计算步数得来结果。
数学理解 :很多,详见最后知识点补充。
问题描述:
# 问题描述
AB 实验同学每天都很苦恼如何可以更好地进行 AB 实验,每一步的流程很重要,我们目标为了缩短所需的步数。
我们假设每一步对应到每一个位置。从一个整数位置 `x` 走到另外一个整数位置 `y`,每一步的长度是正整数,每步的值等于上一步的值 `-1`, `+0`,`+1`。求 `x` 到 `y` 最少走几步。并且第一步必须是 `1`,最后一步必须是 `1`,从 `x` 到 `y` 最少需要多少步。
## 样例说明
- 整数位置 `x` 为 `12`,另外一个整数位置 `y` 为 `6`,我们需要从 `x` 走到 `y`,最小的步数为:`1`,`2`,`2`,`1`,所以我们需要走 `4` 步。
- 整数位置 `x` 为 `34`,另外一个整数位置 `y` 为 `45`,我们需要从 `x` 走到 `y`,最小的步数为:`1`,`2`,`3`,`2`,`2`,`1`,所以我们需要走 `6` 步。
- 整数位置 `x` 为 `50`,另外一个整数位置 `y` 为 `30`,我们需要从 `x` 走到 `y`,最小的步数为:`1`,`2`,`3`,`4`,`4`,`3`,`2`,`1`,所以我们需要走 `8` 步。
## 输入格式
输入包含 `2` 个整数 `x`,`y`。(`0<=x<=y<2^31`)
## 输出格式
对于每一组数据,输出一行,仅包含一个整数,从 `x` 到 `y` 所需最小步数。
## 输入样例
```
12 6
34 45
50 30
```
## 输出样例
```
4
6
8
```
样例:
def solution(x_position, y_position):
# Please write your code here
return -2
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)
解题思路:
1. 首先,我们需要每一步的步长为正整数,且允许每步的步长增加、保持不变或减少。因此,步长的变化是对称的,且我们可以利用中间的最大步长来减少总步数。
2. 其次,第一个和最后一个步长必须是 1,这就意味着步长会有一个逐渐增长的过程到达中间,然后再逐渐减少回到 1。
3. 基于这些条件,我们可以通过分析距离 x - y 的绝对值并判断中间最大步长的位置来推断出最小步数。
为什么对称最优?
“步长变化是对称的” 是指在从位置 x 走到位置 y 的过程中,步长从 1 开始,逐渐增大,达到一个最大值后,再逐渐减小,直到最后一步时步长回到 1。这个步长的变化模式像是一个山峰的形状:前半部分步长逐渐增加,后半部分步长逐渐减小。
对称步长的原因
题目要求:
1. 第一步和最后一步都必须是 1。
2. 每一步只能是上一步步长的 -1、0 或 +1。
3. 目标是最少的步数。
这意味着,你不可能在中途突然减少步长,否则可能会导致需要更多的步骤来达到目标。因此,理想情况下,步长会逐渐增加到某个最大值,然后再逐渐减小回来。这种模式有助于最有效地覆盖距离。
举例说明
假设你要从 x = 12 走到 y = 6,距离为 6。目标是用最少的步数到达终点,且每一步的步长必须满足题目要求。下面我们用对称的步长变化来解释:
步数与步长:
• 第 1 步: 从 12 到 11,步长是 1。
• 第 2 步: 从 11 到 9,步长是 2。
• 第 3 步: 从 9 到 7,步长是 2。
• 第 4 步: 从 7 到 6,步长是 1。
步长变化为 1 → 2 → 2 → 1,这是一个对称的模式。步长先增大到 2,然后保持,最后再减小到 1,这样你能够在最少的步数内从 12 到 6。
为什么对称最优?
步长的对称变化能确保:
1. 前期快速拉开距离: 通过逐渐增加步长,可以在初期快速接近目标。
2. 后期平稳减速: 当接近终点时,逐渐减小步长,确保最后一步是 1。
如果步长在某个时刻突然减小得过早,那么你可能会需要更多的步骤来到达终点。因此,保持对称的增长和减少模式能确保在最少的步数内到达。
非对称的情况
如果不遵循对称模式,假设你从 x = 12 到 y = 6:
• 第 1 步: 1(步长为 1,移动到 11)。
• 第 2 步: 1(步长为 1,移动到 10)。
• 第 3 步: 1(步长为 1,移动到 9)。
• 第 4 步: 2(步长为 2,移动到 7)。
• 第 5 步: 1(步长为 1,移动到 6)。
这种步长变化模式是非对称的,步数是 5,而不是最优的 4 步。显然,这样做会导致多走一步。
总结
“对称”意味着步长会像山峰一样,先增大再减小。这个模式符合题目要求的步长增减约束,并且能够最小化从起点到终点的步数。
所以,对称步长变化的关键点是:
• 前半程步长递增,尽量靠近目标。
• 后半程步长递减,确保步数最少,且第一步和最后一步都是 1。
个人思路 ERROR
初始步长为1
利用当前总路程与最终路程条件判断是否继续增加步长
忽略了必须对称步长,从示例体现
def solution(x_position, y_position):
# 如果起点大于终点,交换它们并递归调用函数
if x_position > y_position:
return solution(y_position, x_position)
# 计算起点和终点之间的距离
distance = y_position - x_position
# 初始化步数为1(第一步必须是1)
steps = 1
# 初始化当前位置为起点加1(因为第一步是1)
current_position = x_position + 1
# 初始化当前步长为1
current_step = 1
while current_position < y_position:
# 如果剩余距离大于当前步长+1,则增加步长
if y_position - current_position > current_step + 1:
current_step += 1
# 如果剩余距离等于当前步长,保持步长不变
elif y_position - current_position == current_step:
pass
# 如果剩余距离小于当前步长,则减少步长
else:
current_step -= 1
# 更新当前位置和步数
current_position += current_step
steps += 1
# 最后一步必须是1,所以如果最后一步不是1,我们需要额外的步骤
if current_step != 1:
steps += 1
return steps
if __name__ == "__main__":
# 测试用例
print(solution(12, 6) == 4)
print(solution(34, 45) == 6)
print(solution(50, 30) == 8)
# 额外的测试用例
print(solution(0, 0) == 1) # 起点等于终点的情况
print(solution(10, 10) == 1) # 起点等于终点的情况
print(solution(0, 1) == 1) # 最小距离的情况
print(solution(0, 3) == 2) # 距离为3的情况
print(solution(100, 200) == 13) # 较大距离的情况
正确答案-无法理解对称算法 太抽象
• 步长的调整逻辑: 要求的是一个对称变化,即步长从 1 开始,逐渐增大到某个峰值,然后再逐渐减少到 1。我们需要根据距离来动态调整步长的增减。
def solution(x_position, y_position):
# 计算距离
distance = abs(x_position - y_position)
# 初始化步数和当前步长
steps = 0
current_step = 1
# 累计的总距离
total_distance = 0
# 当累计的距离小于目标距离时,我们继续增加步数
while total_distance < distance:
steps += 1
total_distance += current_step
# 如果当前步长已经达到 maximum_step - 1 ,则步长不会继续增加
# 步长每两步递增一次,保证平滑增长 控制步长在走过某个步数后再增加:
if steps % 2 == 0:
current_step += 1
return steps
# 测试用例
if __name__ == "__main__":
print(solution(12, 6)) # 输出 4
print(solution(34, 45)) # 输出 6
print(solution(50, 30)) # 输出 8
数学理解
问:依旧不明白对称步长就是最优解,能补充啥知识吗?
你没有缺少相关的知识,只是这个问题涉及到一种“贪心算法”的思路,还有步长变化的规律和对称性对效率的影响。在这个过程中,有一些算法的基本概念可以帮助你理解为什么“对称步长”是最优解。
1. 贪心算法(Greedy Algorithm)
贪心算法是指每一步都选择局部最优的方案,期望最终得到全局最优解。在这个问题中,贪心的策略是:
• 每一步都尽量使用最大的步长,这样可以尽可能快地接近目标,然后当快到达目标时,逐渐减小步长以满足题目要求。
对于“步长必须是上一步的 -1、0 或 +1”这个约束条件,选择对称步长的方案是贪心的:
• 增大步长: 在前期,步长越大,距离目标的差距就缩短得越快。
• 减小步长: 在后期,为了避免超越目标或让步数增加,步长需要逐渐减小。
这种对称结构确保在大部分移动过程中使用的是较大的步长,而最后的步数减少是为了准确到达终点,避免不必要的额外步数。
2. 等差数列的性质
步长的变化符合一种等差递增和递减的结构。考虑你从 1 逐步增加步长:
• 如果你使用步长 1 → 2 → 3 → 4 → 3 → 2 → 1,它实际上形成了一个对称的等差数列。
通过等差数列公式,我们可以知道:
• 距离 S 可以表示为:
\[
S = 1 + 2 + \dots + n + n + \dots + 2 + 1
\]
其中 n 是中间最大步长。
等差数列能快速缩短前半段的距离,而后半段逐渐减速避免超越目标。相比起随机的步长变化,这种结构能更有效地逼近终点,同时满足第一步和最后一步都是 1 的条件。
3. 动态规划的思想
如果你不是很理解贪心算法,动态规划是另一种可以帮助你理解的思路。动态规划的核心是把问题分解为一系列子问题,通过记录和优化子问题的解来求出全局最优解。
在这个问题中,动态规划的思想体现在逐步调整步长。你可以理解为,每一个步骤其实都是根据上一个步长的状态来决定下一步的步长:
• 当前步长要么增加,要么保持不变,要么减少。
• 前半程步长会不断增大,而后半程根据距离和步长关系逐渐减少。
如果没有对称的步长变化,最终结果的步数可能会更多。比如,如果在中途减速过快,后续会因为步长过小而走更多的步数,导致非最优解。
4. 数学上的最短路径
这个问题其实也可以从最短路径问题的角度去理解:
• 从点 x 到 y,如果要求第一步和最后一步是 1,并且步长只能根据上一步的大小调整,你实际上是在一个有“增减限制”的网格中寻找最短路径。
• 步长逐渐增加可以看作是路径上的“加速阶段”,而步长逐渐减小是“减速阶段”。
在这种限制下,对称步长的方案是最优的,因为它能利用最大的步长尽量减少路径长度,并且通过对称变化平滑过渡到终点。
进一步学习
如果你对以上内容还有疑问,建议了解以下几个相关知识点:
1. 贪心算法的原理:为什么贪心策略能找到全局最优解,什么时候它会失败。
2. 等差数列和其求和公式:理解如何利用等差数列快速逼近目标。
3. 动态规划的思想:如何把问题拆解为子问题,并通过最优子结构找到全局最优解。
4. 最短路径问题:图论中的最短路径算法有助于理解如何从一个点最少步骤到达另一个点。
通过这些内容的学习,你会对“为什么对称步长是最优解”有更深的理解。