解题思路
这类题目的本质是利用数组的排列和间隙计算来求最大移动次数。为了确保石子的最终位置连续,这里我们可以按照以下步骤思考:
1.首先对石子的位置进行排序,这样可以清晰地了解石子的位置关系以及石子间的间隙。这里我们使用了一个简单的冒泡排序对石子位置进行排序,确保石子的位置关系是从小到大的顺序。排序后,最小和最大石子的位置可以很容易地确定。
#冒泡排序
n = len(stones)
for i in range(n - 1):
for j in range(n - i - 1):
if stones[j] > stones[j + 1]:
stones[j], stones[j + 1] = stones[j + 1], stones[j]
2.计算从最小石子到最大石子之间,空缺的空间数。空缺数即为能够填补的空间数量,这直接影响最大可移动次数。代码中s1计算的是从最小位置到最大位置之间可以填充的空缺空间数量,即 (最大位置 - 最小位置 + 1) - 石子数量。
# 计算最大空缺数
s1 = stones[-1] - stones[0] + 1 - n
3.端点石子一旦被移动,它们会创建一些不可用的空间(如两端的最小间隙)。我们需要计算这些不可用空间,以确保计算出的移动次数是准确的。我们我们通过计算最小石子和次小石子之间的空隙,和最大石子与次最大石子之间的空隙来得出得出这个值。
# 计算端点石子移除后产生的不可用空间
s2 = min(stones[1] - stones[0] - 1, stones[-1] - stones[-2] - 1)
4.通过计算最大空缺数和不可用空间的差值,即可得到最大移动次数。
# 计算最大移动次数 max_moves = s1 - s2
总结
这类问题由于没有直接数学公式或者优化方法很容易引导人通过遍历来暴力求解,但其实是让人转换一下思路通过空缺求解实体。所以此类问题的求解关键在于对石子位置的排序和间隙的计算,通常用于考察如何通过排序和简单的数学公式推导出最终结果,同时也能锻炼对边界条件的把握和算法优化。这类问题的变形有很多种,比较经典的包括:搬家问题、区间合并问题、最小交换次数问题等等,可以延申出通过排序、动态规划、贪心算法等技巧使得一个序列或区间达到某种特定的状态。