问题描述
小S正在玩一个关于石子的游戏,给定了一些石子,它们位于一维数轴的不同位置,位置用数组 stones 表示。如果某个石子处于最小或最大的一个位置,我们称其为端点石子。
在每个回合,小S可以将一颗端点石子移动到一个未占用的位置,使其不再是端点石子。游戏继续,直到石子的位置变得连续,无法再进行任何移动操作。
你需要帮助小S找到可以移动的最大次数。
测试样例
样例1:
输入:
stones = [7, 4, 9]
输出:2
样例2:
输入:
stones = [6, 5, 4, 3, 10]
输出:3
样例3:
输入:
stones = [1, 2, 3, 4, 5]
输出:0
思路解析
- 关键点:
• 端点石子:位于当前最小位置和最大位置的石子。
• 移动规则:只能移动端点石子,每次移动到一个未占用的位置。
• 目标:将所有石子的位置调整为连续的,即石子之间没有空隙。
- 可移动的最大次数:
• 观察可以发现,每次移动都减少端点石子的数量或将它们填充到空缺的位置。最终,当所有石子连续时,无法继续移动。
- 核心问题:
• 初始状态下,石子分布是不连续的。
• 需要模拟石子的移动,计算可以操作的总次数。
算法过程
- 排序石子:
为了便于分析石子之间的间隙和连续性,我们首先将数组 stones 按升序排列。
- 计算间隙:
连续的石子之间不需要操作,只有当石子之间存在间隙时,才需要移动。两个端点石子的移动能够逐步填补这些间隙。
- 最大移动次数公式:
假设数组长度为 n ,端点分别为最小值和最大值 min(stones) 和 max(stones) 。可以将最大移动次数表示为:
最大移动次数 = 最大端点间距 - (n - 1)
其中,最大端点间距为:
max(stones)- min(stones)
减去石子的总数减一(即理想连续序列的间距总和)。
- 模拟石子的移动:
每次将端点石子移动到可用的最近位置,并记录操作次数,直到石子变得连续。
def max_moves_to_continuous(stones):
# 1. 将石子位置排序
stones.sort()
n = len(stones)
# 2. 计算最大移动次数
max_moves = stones[-1] - stones[0] - (n - 1)
return max_moves
# 测试样例
stones = [7, 4, 9]
print(max_moves_to_continuous(stones)) # 输出:2
思考与分析
1. 为什么排序是必要的?*
• 排序后,石子的分布就可以通过简单的间距计算判断是否连续,同时能够轻松确定端点石子。
2. 最大移动次数的直观理解:*
• 最大移动次数对应于从当前石子分布填补所有间隙所需的操作次数。例如,在 stones = [7, 4, 9] 中,初始状态有两个间隙:
• 从 4 到 7,有一个间距 2。
• 从 7 到 9,有一个间距 1。
合计间隙数量为 3,扣除连续的 (n-1 = 2) 后,最大移动次数为 2。
3. 延伸问题:如何找到最小移动次数?*
• 另一个可能的挑战是计算最少移动次数,这需要考虑具体的移动策略。通过滑动窗口方法可以快速找到填补所有间隙所需的最少操作次数。
4. 实际应用:*
• 该问题可以拓展到区间操作、数组离散化等场景,适用于需要模拟分布调整的优化问题。