跳水板

标签: 数组 数学

难度: Easy

你正在使用一堆木板建造跳水板。有两种类型的木板,其中长度较短的木板长度为shorter,长度较长的木板长度为longer。你必须正好使用k块木板。编写一个方法,生成跳水板所有可能的长度。

返回的长度需要从小到大排列。

示例 1

输入:
shorter = 1
longer = 2
k = 3
输出: [3,4,5,6]
解释:
可以使用 3 次 shorter,得到结果 3;使用 2 次 shorter 和 1 次 longer,得到结果 4 。以此类推,得到最终结果。

提示:

  • 0 < shorter <= longer
  • 0 <= k <= 100000

Submission

运行时间: 28 ms

内存: 20.5 MB

class Solution:
    def divingBoard(self, shorter: int, longer: int, k: int) -> List[int]:
        ret = []
        if k == 0:
            return ret
        if shorter == longer:
            ret.append(k * shorter)
            return ret
        else:
            length_min = shorter * k
            length_max = longer * k
            dist = longer - shorter
            return list(range(length_min, length_max + 1, dist))

Explain

题解的思路是首先考虑边界情况,即如果k等于0,则没有木板可以使用,返回空列表。如果短木板和长木板的长度相同,则无论如何组合,最终的跳水板长度都是相同的,直接返回长度为k乘以短木板长度的列表。如果短木板和长木板长度不同,则可以通过改变使用短木板和长木板的数量来获取不同长度的跳水板。最短的跳水板长度是全部使用短木板,最长的跳水板长度是全部使用长木板,中间的长度可以通过逐渐替换短木板为长木板来实现,每次替换增加的长度是长木板和短木板长度之差。因此,可以使用range函数生成从最短长度到最长长度,步长为长短木板长度之差的序列。

时间复杂度: O(k)

空间复杂度: O(k)

class Solution:
    def divingBoard(self, shorter: int, longer: int, k: int) -> List[int]:
        ret = []
        if k == 0:
            return ret
        if shorter == longer:
            ret.append(k * shorter)
            return ret
        else:
            length_min = shorter * k
            length_max = longer * k
            dist = longer - shorter
            return list(range(length_min, length_max + 1, dist))

Explore

当`shorter`等于`longer`时,无论如何组合短木板和长木板,所得到的跳水板长度都是一样的,因为它们的长度相同。因此,不管怎样组合这k块木板,最终的长度都是k乘以`shorter`(或`longer`,因为它们相等)。在这种情况下,只有一种可能的长度,所以直接返回这个长度的列表,无需考虑其他长度。

使用range函数可以更有效地生成所有可能的跳水板长度,从最短长度到最长长度,步长为`longer - shorter`。这种方法利用了数学规律,即每增加一块长木板并去掉一块短木板,总长度就增加`longer - shorter`。这样不仅代码更简洁,而且执行效率更高,因为不需要逐个计算每种组合的长度,只需要按固定步长递增即可覆盖所有可能的长度。

这种步长设置适用于所有的输入情况。步长`longer - shorter`表示每次用一块长木板替换一块短木板能增加的长度。即使`shorter`和`longer`非常接近,这个步长也有效,因为即便两者的差值很小,长度的变化仍然是线性的。在极端情况下,如果`shorter`和`longer`相等,步长会变为0,这种情况在代码中已经特殊处理,直接返回单一长度。