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

158 阅读4分钟

石子移动问题

问题概述

一维数轴上有一些石子,它们位于一维数轴的不同位置,处于最大值或最小值位置的石子被称为端点石子。
在每次移动中,可以将一颗端点石子移动到一个未被占用的位置,同时其不能再是端点石子。重复移动,直到石子的位置变得连续,无法再进行任何移动操作。
stones=[6,5,4,3,10]为例,首先将stones进行升序排序stones=[3,4,5,6,10]以便观察移动顺序,接着进行移动,石子的移动顺序是:
第一步:移动3号位置上的石子至7号位置,石子顺序变为 [4,5,6,7,10]。
第二步:移动4号位置上的石子至8号位置,石子顺序变为 [5,6,7,8,10]。
第三步:移动5号位置上的石子至8号位置,石子顺序变为 [6,7,8,9,10]。
石子的位置连续,无法在进行移动操作,最大移动次数为3。

题目解析

代码展示

def solution(stones: list) -> int:
    stones.sort()
    n=len(stones)
    if n==1:
        return 0 #边界条件

    result=max(stones[n-1]-stones[1]+1-(n-1),stones[n-2]-stones[0]+1-(n-1))
    return result

思路分析

  1. 排序

    • 首先,对石子位置进行排序。这是为了简化后续的计算,因为排序后我们可以更容易地处理石子的连续性问题。
  2. 边界条件

    • 如果石子只有一个,那么无需移动,直接返回0。
  3. 计算最大移动次数

    • 排序后,考虑两种情况:

      • 左端点右移:将所有石子向右移动,使得最左侧的石子(stones[0])移到某个位置,使得所有石子连续。这时,我们需要计算移动后的连续石子序列的右边界(即最右侧石子的目标位置)与当前最右侧石子(stones[n-1])的差值,减去需要移动的石子数量(n-1),得到右移情况下的最大移动次数。
      • 右端点左移:将所有石子向左移动,使得最右侧的石子(stones[n-1])移到某个位置,使得所有石子连续。这时,我们需要计算移动后的连续石子序列的左边界(即最左侧石子的目标位置)与当前最左侧石子(stones[0])的差值,减去需要移动的石子数量(n-1),得到左移情况下的最大移动次数。
  4. 结果

    • 比较上述两种情况下的最大移动次数,取较大值作为结果返回。

个人思考与分析

首先,我明确了问题的目标:使所有石子位置连续,并在此过程中最大化移动次数。同时,我也注意到了问题的限制条件,即每次只能移动最左侧或最右侧的石子。输入则是一个表示石子位置的数组。

为了解决这个问题,我首先想到了对石子位置进行排序。排序后的石子位置将更容易处理,因为我可以清晰地识别出端点石子,即数组的第一个和最后一个元素。同时,我也考虑了边界条件,如果只有一个石子,那么它自然是“连续”的,无需移动,直接返回0即可。

接下来,我深入思考了移动策略。为了最大化移动次数,我需要考虑如何将石子移动到连续的位置。由于每次只能移动端点石子,这实际上是一个“填补空隙”的过程。我意识到,可以通过计算当前最右侧石子与理想连续序列中左端点石子位置之间的空隙,以及当前最左侧石子与理想连续序列中右端点石子位置之间的空隙,来确定移动的次数。

然后,对于上述两种情况,我分别计算了移动后的连续石子序列的边界与当前石子序列边界的差值,并减去了需要移动的石子数量(即数组长度减一)。最后,我比较了两种情况下的最大移动次数,并返回了较大值。

总的来说,这个问题的解决过程让我加深了对算法和数据结构的理解,也锻炼了我分析和解决优化问题的能力。我意识到,在解决这类问题时,首先需要明确问题的目标和限制条件,然后进行深入的思考和分析,找到解决问题的策略和方法。最后,通过实现和测试来验证算法的正确性和效率。这种思考和分析方法对我未来的学习和工作都将产生积极的影响。