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

347 阅读3分钟

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

1. 问题描述

给定一些石子, 他们位于一个数轴上的不同位置,位置通过数组进行表示,例如一个 [4,7,9] 的数组,就表示有3个石子,分别在位置4,位置7,位置9上。 这时候我们称最大、最小的两个位置为端点石子。

例如这样理解 image.png 在这个数轴上,4,7,9三个位置分别有三个石子,其中49就是所谓的端点石子了 现在,需要移动这些端点石子,要求将其移动后不再是端点石子, 问最大的移动次数是多少?

2. 思考如何解决

  其实,这些间隔都是石子可以放入的点,但并不是简单的把间隔都加起来就是最大的移动次数,由于需要维持端点的原因,必须会有一处间隔没办法用到。

  例如如果是像 [4,7,9] 这样的数组,最大移动次数方法应该是这样的,将端点石子移动到最大间隔内的点,先位置9的石子移动到6,这时候,端点石子就变成了4和7

image.png 因为6和7之间是没有间隔的,所以这时候再次移动端点石子,就只能是将位置7的石子移动到5了

image.png 这时候就是最大的移动次数:2次,所以我们就发现,最开始有1个间隔是没有放入任何石子的。也就是8那个位置。

如果我们先移动位置4的石子,会怎么样呢?结果会发现,位置4的石子只能移动到位置8,也就是2个间隔被浪费掉了。

image.png 这时候,最大次数只能是1了。

依照这个思路,我们会发现,要有最大的移动次数。 必须舍去由端点石子和其相邻的石子构成的一个间隔。并且要把端点石子移动到端点石子和它相邻的石子不会有任何间隔的位置。

即上述案例中的两种方案都是这样的。只是前者方案是浪费了1个间隔,而后者方案则是浪费了2个间隔。所以造成一个方案只能移动1次,而另一个方案可以移动2次。很明显,我们要的就是浪费较少间隔的方案。

问题简化与思路

  也就是说,整个石子移动问题,可以简化成求由端点石子和其相邻石子间隔最小浪费问题。所以我们的思路可以是这样的。

题目给定了我们一个列表,里面含有石子的位置,先将石子进行排序,这样数组的第一个元素和最后一个元素就是端点石子所在的位置了。 定义一个间隔列表,把他们的间隔记录在内,直到遍历完整个列表以后,再对第一个间隔和最后一个间隔进行比较,选出最小的浪费,把这些间隔再求和,便能得到最大移动次数的结果了。算法示意图如下:

image.png

代码实现

    # 对给定的列表进行排序
    stones.sort()
    # 如果只有1个石子, 不需要移动
    if len(stones) == 1:
        return 0
    # 定义间隔列表
    gaps = []
    for i in range(1, len(stones)):
        gaps.append(stones[i] - stones[i-1] - 1)
    # 选取最小浪费的间隔进行求和,获得最大移动次数
    if gaps[0] > gaps[-1]:
        max_moves = sum(gaps[:-1])
    else:
        max_moves = sum(gaps[1:])
    return max_moves

心得总结

  这道题如果使用AI,它好像并没有搞清楚题目的意思,虽然这并不是什么难题,但是有一个清晰的思路是解决问题的关键,有时候我会发现太过于依靠AI了。当AI解决不了问题的时候,心情就会变得烦躁,现在的我,已经不敢想象没有AI的时代了。