📜  数组中 K 个最小和最大斐波那契数的总和和乘积(1)

📅  最后修改于: 2023-12-03 15:10:21.279000             🧑  作者: Mango

数组中 K 个最小和最大斐波那契数的总和和乘积

介绍

本题目要求在一个数组中,找出 K 个最小和最大的斐波那契数,并计算它们的总和和乘积。斐波那契数列是指以 0 和 1 开头,后面的项为前两项之和的数列。具体如下:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

为了方便起见,本题中规定,如果一个数不是斐波那契数列中的数,则不计入答案。

示例输入输出
示例 1

输入:

nums = [1, 7, 10, 8, 15]
k = 3

输出:

total_sum = 17
total_product = 56

说明:

在输入数组中,有以下斐波那契数:

1, 8, 13

其中,最小的三个是 1, 8, 10,它们的和是 19,乘积是 80。但因为 10 不是斐波那契数列中的数,所以最小的三个数实际上是 1, 8, 13,它们的和是 22,乘积是 104。因此,输出结果为 22 和 104。

示例 2

输入:

nums = [13, 7, 21, 8, 34, 1]
k = 4

输出:

total_sum = 55
total_product = 24048

说明:

在输入数组中,有以下斐波那契数:

1, 8, 13, 21, 34

其中,最大的四个是 34, 21, 13, 8,它们的和是 76,乘积是 764448。但因为 1 不是斐波那契数列中的数,所以最大的四个数实际上是 34, 21, 13, 8,它们的和是 76,乘积是 24048。因此,输出结果为 76 和 24048。

解题思路
  1. 首先将所有斐波那契数放入一个集合中
  2. 对于最小的 K 个数,我们可以通过桶排来完成。定义一个大小为斐波那契数列长度的桶数组,遍历原数组并将每个数出现的次数存储到桶数组对应下标的位置上。然后从桶数组的头部开始取 K 个数,直到取到了 K 个不是 0 的数为止。
  3. 对于最大的 K 个数,我们也可以通过桶排来完成。定义一个大小为斐波那契数列长度的桶数组,遍历原数组并将每个数出现的次数存储到桶数组对应下标的位置上。然后从桶数组的尾部开始取 K 个数,直到取到了 K 个不是 0 的数为止。
  4. 最后将最小的 K 个数的求和以及最大的 K 个数的求积计算出来即可。
代码实现
def fibonacci():
    """
    生成斐波那契数列
    """
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b


def fibonacci_sum_product(nums, k):
    fib = set()
    for x in fibonacci():
        if x > 10**5:  # 只需考虑小于 10^5 的斐波那契数
            break
        fib.add(x)

    count = [0] * len(fib)
    for num in nums:
        if num in fib:
            count[list(fib).index(num)] += 1

    total_sum = 0
    for i in range(len(count)):
        for j in range(count[i]):
            total_sum += list(fib)[i]

    min_numbers = []
    for i in range(len(count)):
        for j in range(count[i]):
            min_numbers.append(list(fib)[i])
            if len(min_numbers) == k:
                return sum(min_numbers), None

    max_numbers = []
    for i in range(len(count) - 1, -1, -1):
        for j in range(count[i]):
            max_numbers.append(list(fib)[i])
            if len(max_numbers) == k:
                total_product = 1
                for x in max_numbers:
                    total_product *= x
                return None, total_product

    return None, None
复杂度分析
  • 时间复杂度:$O(n\log n)$,其中 $n$ 表示数组的长度,需要遍历每个数,并对斐波那契数列做初始化和桶排,时间复杂度均为 $O(\log n)$。
  • 空间复杂度:$O(\log n)$,需要保存斐波那契数列,空间复杂度为 $O(\log n)$。