class Solution:
def findMinFibonacciNumbers(self, k: int) -> int:
fibs = [1, 1]
while fibs[-1] < k:
fibs.append(fibs[-1] + fibs[-2])
count = 0
i = len(fibs) - 1
while k > 0:
if fibs[i] <= k:
k -= fibs[i]
count += 1
i -= 1
return count
class Solution {
public:
int findMinFibonacciNumbers(int k) {
vector<int> fibs = {1, 1};
while (fibs.back() < k) {
fibs.push_back(fibs.back() + fibs[fibs.size() - 2]);
}
int count = 0, i = fibs.size() - 1;
while (k > 0) {
if (fibs[i] <= k) {
k -= fibs[i];
count++;
}
i--;
}
return count;
}
};
class Solution {
public int findMinFibonacciNumbers(int k) {
List<Integer> fibs = new ArrayList<>();
fibs.add(1);
fibs.add(1);
while (fibs.get(fibs.size() - 1) < k) {
int n = fibs.size();
fibs.add(fibs.get(n - 1) + fibs.get(n - 2));
}
int count = 0, i = fibs.size() - 1;
while (k > 0) {
if (fibs.get(i) <= k) {
k -= fibs.get(i);
count++;
}
i--;
}
return count;
}
}
var findMinFibonacciNumbers = function(k) {
const fibs = [1, 1];
while (fibs[fibs.length - 1] < k) {
fibs.push(fibs[fibs.length - 1] + fibs[fibs.length - 2]);
}
let count = 0, i = fibs.length - 1;
while (k > 0) {
if (fibs[i] <= k) {
k -= fibs[i];
count++;
}
i--;
}
return count;
};
Given a positive integer k
, you are to find the minimum number of Fibonacci numbers whose sum is equal to k
. Each Fibonacci number can be used at most once in the sum. Recall that the Fibonacci sequence is defined as F(1) = 1, F(2) = 1, F(n) = F(n-1) + F(n-2)
for n > 2
.
You must return the smallest count of Fibonacci numbers such that their sum equals exactly k
. You cannot reuse any Fibonacci number, and it is guaranteed that there is always at least one valid solution for any valid input.
At first glance, this problem resembles the classic "coin change" problem, where you want to make a certain amount using the fewest coins, each with a limited supply (in this case, each Fibonacci number can be used once). The naive approach would be to try all combinations of Fibonacci numbers less than or equal to k
and see which combination sums to k
with the smallest count.
However, this brute-force approach is not efficient, especially as k
grows large, because there are exponentially many combinations. The key insight is to notice that Fibonacci numbers form a special sequence, and there is a greedy way to build up the sum: always use the largest Fibonacci number not exceeding the remaining k
, subtract it, and repeat until k
becomes zero. This works because of a property known as Zeckendorf's Theorem, which states that every positive integer can be uniquely represented as a sum of non-consecutive Fibonacci numbers.
We use a greedy algorithm to solve the problem efficiently. Here’s how the approach works step-by-step:
k
. We start with [1, 1] and keep adding the sum of the last two numbers until we reach or exceed k
.
k
.
k
and increment a counter.
k
(using the next largest Fibonacci number that does not exceed the current k
).
k
becomes zero.
k
.
This approach is efficient because at each step, we reduce k
by the largest possible amount, minimizing the number of steps needed.
Let’s walk through an example with k = 19
:
k = 6
. Count = 1.
k = 1
. Count = 2.
k = 0
. Count = 3.
Brute-force Approach:
k
. This is exponential in the number of Fibonacci numbers (O(2^n)
), which is not feasible for large k
.
k
takes O(log k)
time, since Fibonacci numbers grow exponentially. The greedy selection step also takes O(log k)
time, as we may subtract at most as many times as there are Fibonacci numbers ≤ k
.
k
requires O(log k)
space.
Overall, the greedy approach is highly efficient and suitable for the problem's constraints.
The problem of finding the minimum number of Fibonacci numbers whose sum is k
can be solved efficiently using a greedy approach, thanks to Zeckendorf's Theorem. The solution involves generating all Fibonacci numbers up to k
and iteratively subtracting the largest possible Fibonacci number until we reach zero. This method is both fast and elegant, leveraging the unique properties of the Fibonacci sequence to avoid brute-force search.