石子移动问题 | 豆包MarsCode AI刷题

40 阅读3分钟

问题描述

小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

思路解析

  1. 关键点

端点石子:位于当前最小位置和最大位置的石子。

移动规则:只能移动端点石子,每次移动到一个未占用的位置。

目标:将所有石子的位置调整为连续的,即石子之间没有空隙。

  1. 可移动的最大次数

• 观察可以发现,每次移动都减少端点石子的数量或将它们填充到空缺的位置。最终,当所有石子连续时,无法继续移动。

  1. 核心问题

• 初始状态下,石子分布是不连续的。

• 需要模拟石子的移动,计算可以操作的总次数。

算法过程

  1. 排序石子

为了便于分析石子之间的间隙和连续性,我们首先将数组 stones 按升序排列。

  1. 计算间隙

连续的石子之间不需要操作,只有当石子之间存在间隙时,才需要移动。两个端点石子的移动能够逐步填补这些间隙。

  1. 最大移动次数公式

假设数组长度为  n ,端点分别为最小值和最大值 min(stones) 和 max(stones) 。可以将最大移动次数表示为:

最大移动次数 = 最大端点间距 - (n - 1)

其中,最大端点间距为:

max(stones)- min(stones)

减去石子的总数减一(即理想连续序列的间距总和)。

  1. 模拟石子的移动

每次将端点石子移动到可用的最近位置,并记录操作次数,直到石子变得连续。

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. 实际应用:*

• 该问题可以拓展到区间操作、数组离散化等场景,适用于需要模拟分布调整的优化问题。