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

78 阅读3分钟

题目分析

石子移动问题要求找到石子位置连续所需的最大移动次数。题目描述的核心是:

  1. 石子的位置连续:意味着在数轴上没有任何间隙,石子位置从 min(stones)max(stones) 恰好形成一个连续的区间。
  2. 端点石子:当前位于最左或最右的石子,因其位置最为边缘,可以在每回合被移动到其他未被占用的位置。

问题求解

为了实现石子位置的连续化,我们需要:

  1. 每次将端点石子移动到数轴上的某个空位。
  2. 计算所需的最大移动次数

通过分析可知,最大移动次数直接与石子分布的间隔有关。如果间隔很大,就需要较多次移动才能填充这些空隙。

解题思路

  1. 排序:将石子的初始位置排序,方便计算连续性。
  2. 计算最大移动次数
    • 假设固定左端或右端,计算中间区域需要多少步才能连续。
    • 取两种情况下的最大值。

代码实现

以下是解题代码及说明:

def solution(stones: list) -> int:
    # 对石子位置排序,确保可以顺序处理
    stones.sort()
    n = len(stones)
    
    # 如果石子数少于等于1,则不需要移动
    if n <= 1:
        return 0
    
    # 最大移动次数计算:
    # 1. 以最左端石子为固定点,计算右侧需要填补的空隙
    # 2. 以最右端石子为固定点,计算左侧需要填补的空隙
    max_moves = max(stones[-1] - stones[1] - (n - 2), stones[-2] - stones[0] - (n - 2))
    
    return max_moves

# 测试用例
if __name__ == '__main__':
    print(solution(stones=[7, 4, 9]) == 2)  # 测试例1:两步使石子连续
    print(solution(stones=[6, 5, 4, 3, 10]) == 3)  # 测试例2:三步使石子连续
    print(solution(stones=[1, 2, 3, 4, 5]) == 0)  # 测试例3:无需移动

示例分析

示例1

输入:

stones = [7, 4, 9]

排序后:

[4, 7, 9]

计算最大移动:

  • 固定左端点 4,需要填补 79 之间的空隙,共 2 步。
  • 固定右端点 9,需要填补 47 之间的空隙,共 2 步。

返回 2

示例2

输入:

stones = [6, 5, 4, 3, 10]

排序后:

[3, 4, 5, 6, 10]

计算最大移动:

  • 固定左端点 3,需要填补 106 之间的空隙,共 3 步。
  • 固定右端点 10,需要填补 36 之间的空隙,共 3 步。

返回 3

示例3

输入:

stones = [1, 2, 3, 4, 5]

排序后:

[1, 2, 3, 4, 5]

计算最大移动:

  • 不需要任何移动,因为已经连续。

返回 0

复杂度分析

  1. 时间复杂度

    • 排序操作需要 (O(n \log n)),是主要的计算量。
    • 其他计算如间隔和最大值的比较是 (O(1))。
    • 综合复杂度为 (O(n \log n))。
  2. 空间复杂度

    • 仅使用了常量级额外空间,复杂度为 (O(1))。

总结

该问题通过排序、间隔计算即可求解,主要考察的是理解最大间隙的计算方法。代码清晰简洁,适用于多种场景。