要解析这个问题,我们首先要理解几个关键点:
- 初始状态:石子位于一维数轴的不同位置,位置由数组
stones表示。 - 端点石子:位于数轴最小或最大位置的石子。
- 移动规则:每个回合可以将一个端点石子移动到一个未占用的位置。
- 游戏结束条件:石子的位置变得连续,即任意两个相邻石子的位置差为1。
我们的目标是找到可以移动的最大次数。
解题思路
-
排序:首先,对石子位置进行排序,这样我们可以方便地处理端点石子。
-
计算空隙:排序后,计算相邻石子之间的空隙(即位置差)。
-
模拟移动:
- 每次选择一个端点石子(最小或最大位置的石子)。
- 尝试将其移动到相邻的未占用位置(即填补一个空隙)。
- 更新石子位置和空隙。
-
统计移动次数:记录每次成功的移动,直到所有石子位置连续。
然而,直接模拟移动可能非常复杂且效率低下,因为我们需要考虑所有可能的移动顺序和结果。幸运的是,这个问题有一个更简洁的解法。
简洁解法
由于最终目标是使所有石子位置连续,我们可以观察到:
- 移动端点石子实际上是在填补空隙。
- 移动的最大次数等于初始状态下所有空隙的总和(因为每个空隙都需要被填补一次)。
- 但是,由于移动是连续的,并且最终所有石子都要紧密相连,因此一些移动可能会“抵消”掉(例如,将一个石子从一端移动到中间,然后另一个石子从另一端移动到刚才空出的位置)。
为了找到可以移动的最大次数,我们可以这样做:
- 对石子位置进行排序。
- 计算相邻石子之间的空隙。
- 由于最终石子会紧密相连,我们可以假设它们最终形成一个连续的区间
[start, start + n - 1],其中n是石子的数量。 - 计算当前石子位置到这个连续区间的“偏移量”,这个偏移量实际上就是需要移动的次数(因为每个偏移都对应一个空隙需要填补)。
实现步骤
- 排序石子位置数组
stones。 - 计算目标连续区间的起始位置
start,这可以通过(最小位置 + 最大位置 - n + 1) // 2来计算(这里n是石子的数量)。 - 遍历排序后的石子位置,计算每个位置到目标连续区间的偏移量,并累加这些偏移量的绝对值(因为偏移需要被填补)。
代码实现
在这个实现中,我们首先对石子位置进行排序,然后计算目标连续区间的起始位置 target_start。接着,我们遍历每个石子位置,计算它到目标位置的偏移量,并累加这些偏移量的绝对值作为移动次数。
注意:这个解法是基于观察得出的,它假设了最终石子会形成一个连续的区间,并且所有空隙都需要被填补一次。由于移动是连续的,并且最终状态是唯一的(所有石子紧密相连)