1414. 和为 K 的最少斐波那契数字数目

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 。

解题思路:

读完题时第一想法:

  • 先获取斐波那契数组
  • 然后用dp找到最优解
  • 回溯找到组成最优解的个数

但是做到后面回溯找到最优解才发现,用dp只不过是为了证明可以用斐波那契的那些数来组成k(最优解),即解可以得到!!!但是题目已经明确指出当前数可以用数组来得到!所以可以把dp给省略,这样就不会超时!

代码

第一次,用dp找最优解,超时!
class Solution {
public:
int findMinFibonacciNumbers(int k) 
{
	vector<int> nums;
	nums.push_back(1);
	nums.push_back(1);
	int index = 2;
	int num = 0;
	while (num <= k)
	{
		num = nums[index - 1] + nums[index - 2];
		nums.push_back(num);
		index += 1;
	}
	
	int n = nums.size();
	vector<vector<int>> dp(n,vector<int>(k + 1, 0));
	
	for (int i = nums[0]; i <= k; i++)
	{
		dp[0][i] = nums[0];
	}

	for (int i = 1; i < nums.size(); i++)
	{
		for (int j = 0; j <= k; j++)
		{
			if (j > nums[i])
				dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i]);
			else
				dp[i][j] = dp[i - 1][j];
		}
	}
	
	int res = k;
	int r = 0;
	for (int i = n - 1; i >= 0; i--)
	{
		if (nums[i] <= res)
		{
			res -= nums[i];
			r++;
		}
	}

	return r;
}
};
第二次,可以把dp省略,因为题目已经表明这个数字一定可以用这个数组得到,不需要自己去证明
class Solution {
public:
int findMinFibonacciNumbers(int k) 
{
	vector<int> nums;
	nums.push_back(1);
	nums.push_back(1);
	int index = 2;
	int num = 0;
	while (num <= k)
	{
		num = nums[index - 1] + nums[index - 2];
		nums.push_back(num);
		index += 1;
	}
	
	int n = nums.size();	
	int res = k;
	int r = 0;
	for (int i = n - 1; i >= 0; i--)
	{
		if (nums[i] <= res)
		{
			res -= nums[i];
			r++;
		}
	}

	return r;
}
};
总结
第一次做的时候被限制了思维,想着用dp然后回找来找到最优解.但是如果数过大就超时了,所以想到优化时才看到我在找最优解时压根就没用到dp数组.所以就把dp去除,即可得到最终结果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

公仔面i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值