1414-和为 K 的最少斐波那契数字数目
给你数字 k
,请你返回和为 k
的斐波那契数字的最少数目,其中,每个斐波那契数字都可以被使用多次。
斐波那契数字定义为:
- F1 = 1
- F2 = 1
- Fn = Fn-1 + Fn-2 , 其中 n > 2 。
数据保证对于给定的 k
,一定能找到可行解。
示例 1:
**输入:** k = 7
**输出:** 2
**解释:** 斐波那契数字为:1,1,2,3,5,8,13,……
对于 k = 7 ,我们可以得到 2 + 5 = 7 。
示例 2:
**输入:** k = 10
**输出:** 2
**解释:** 对于 k = 10 ,我们可以得到 2 + 8 = 10 。
示例 3:
**输入:** k = 19
**输出:** 3
**解释:** 对于 k = 19 ,我们可以得到 1 + 5 + 13 = 19 。
提示:
1 <= k <= 10^9
方法一:贪心
思路
首先找到所有不超过 k 的斐波那契数字,然后每次贪心地选取不超过 k 的最大斐波那契数字,将 k 减去该斐波那契数字,重复该操作直到 k 变为 0,此时选取的斐波那契数字满足和为 k 且数目最少。
证明
为了证明上述方案选取的斐波那契数字数目最少,只需要证明存在一种选取斐波那契数字数目最少的方案,该方案选取了不超过 k 的最大斐波那契数字。
当选取斐波那契数字数目最少时,不可能选取两个相邻的斐波那契数。
假设选取了两个相邻的斐波那契数字 F_x 和 F_{x + 1,则根据斐波那契数字的定义,这两个斐波那契数字之和为后一个斐波那契数字:
F_{x + 2} = F_x + F_{x + 1
因此可以用 F_{x + 2 代替 F_x 和 F_{x + 1,选取的斐波那契数字的总和不变,选取的斐波那契数字的数目减少 1 个,比选取 F_x 和 F_{x + 1 的方案更优。
一定存在一种选取斐波那契数字数目最少的方案,使得选取的每个斐波那契数字各不相同。
假设 F_x 被选取了两次。当 x \le 2 时,F_x = 1,可以用 F_3 = 2 代替两个 F_x,此时选取的斐波那契数字的数目减少 1 个。当 x > 2 时,存在以下关系:
2 \times F_x = (F_{x - 2} + F_{x - 1}) + F_x = F_{x - 2} + (F_{x - 1} + F_x) = F_{x - 2} + F_{x + 1
因此当 x > 2 时,如果 F_x 被选取了两次,则可以换成 F_{x - 2 和 F_{x + 1。
根据上述两个结论,必须选取不超过 k 的最大斐波那契数字,才能使得选取的斐波那契数字满足和为 k 且数目最少。
用 F_m 表示不超过 k 的最大斐波那契数字。如果不选择 F_m,则考虑选取的斐波那契数字之和可能的最大值,记为 N。根据上述两个结论,选取的斐波那契数字中不存在相邻的斐波那契数字,也不存在重复的斐波那契数字,因此可以得到 N 的表达式:
N = \begin{cases}
F_{m - 1} + F_{m - 3} + \ldots + F_4 + F_2, &m是奇数 \是偶数
F_{m - 1} + F_{m - 3} + \ldots + F_3 + F_1, &m
\end{cases}当 m 是奇数时,N 的值计算如下:
\begin{aligned}
N &= F_{m - 1} + F_{m - 3} + \ldots + F_4 + F_2 \
&= F_{m - 1} + F_{m - 3} + \ldots + F_4 + F_2 + F_1 - F_1 \
&= F_{m - 1} + F_{m - 3} + \ldots + F_4 + F_3 - F_1 \
&= F_{m - 1} + F_{m - 3} + \ldots + F_5 - F_1 \
&= \ldots \
&= F_{m - 1} + F_{m - 2} - F_1 \
&= F_m - 1 \
&< F_m
\end{aligned}此时 N < F_m,由于 F_m \le k,因此 N < k。如果不选择 F_m,则选取的斐波那契数字之和一定小于 k,因此必须选择 F_m。
当 m 是偶数时,N 的值计算如下:
\begin{aligned}
N &= F_{m - 1} + F_{m - 3} + \ldots + F_3 + F_1 \
&= F_{m - 1} + F_{m - 3} + \ldots + F_3 + F_2 \
&= F_{m - 1} + F_{m - 3} + \ldots + F_4 \
&= \ldots \
&= F_{m - 1} + F_{m - 2} \
&= F_m
\end{aligned}此时 N = F_m,\dfrac{m}{2 个斐波那契数字之和等于 F_m,用一个 F_m 替换 \dfrac{m}{2 个斐波那契数字,选取的斐波那契数字数目不变或减少(只有当 m = 2 时,选取的斐波那契数字数目不变)。
综上所述,无论 m 是奇数还是偶数,都需要选取 F_m,即不超过 k 的最大斐波那契数字,才能使得选取的斐波那契数字满足和为 k 且数目最少。
代码
1 | class Solution: |
1 | class Solution { |
1 | public class Solution { |
1 | class Solution { |
1 | int findMinFibonacciNumbers(int k){ |
1 | func findMinFibonacciNumbers(k int) (ans int) { |
1 | var findMinFibonacciNumbers = function(k) { |
复杂度分析
时间复杂度:O(\log k),其中 k 为给定的整数。需要找到所有不超过 k 的斐波那契数字,然后计算和为 k 的最少斐波那契数字数目,不超过 k 的斐波那契数字的个数是 O(\log k) 个。
空间复杂度:O(\log k),其中 k 为给定的整数。需要 O(\log k) 的空间存储所有不超过 k 的斐波那契数字。