ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JAVA练习76-和为 K 的最少斐波那契数字数目

2022-02-03 21:33:40  阅读:167  来源: 互联网

标签:JAVA 数字 int max 斐波 76 那契 Fn


给你数字 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

分析:

方法1:贪心+递归

其实这道题很容易看出 k 的组成数字都有离它最近的斐波那契数字,只要每次找到离它最近的斐波那契数字,然后 k 减去最近的斐波那契数字,再继续找新 k 的最近斐波那契数字,直到 k 为 0,那么找的次数就为最少数目,用一个递归可以轻松解决。但是这些思路都是建立在 k 的组成数字一定有离它最近的数 的基础上,接下来我们来证明这个条件是正确的:

令离 k 最近的数为 Fn,易证 k 的组成一定不含连续数字,因为连续数字加起来就是一个新的斐波那契数字,所以假设 k 的组成不含 Fn,那么 k 的最大值 max 满足:

  1. 令 max  = F(n - 1) + F(n - 3) + ... + F1 (n 为 偶数)或 max = F(n - 1) + F(n - 3) + ... + F2(n 为 奇数)
  2. 因为 Fn = F(n - 1) + F(n - 2) = F(n - 1) + F(n - 3) + F(n - 4) = F(n - 1) + F(n - 3) + F(n - 5) + ... + F1 + F1(n 为 偶数)或  F(n - 1) + F(n - 3) + F(n - 5) + ... + F2 + F1(n 为 奇数)
  3. 所以Fn >= max
  4. 因为 k >= Fn
  5. 所以在 F(n - ?) 不重复的情况下,一定有 Fn

下面考虑重复的情况:

  1. 令 max = F(n - 1) + F(n - 1)
  2. 因为 F(n - 1) = F(n - 2) + F(n - 3)
  3. 所以 max = F(n - 1) + F(n - 2) + F(n - 3) = Fn + F(n - 3)
  4. 所以在重复的情况下,重复的运算式也可以转换为含 Fn 运算式

因此,无论什么情况,k 的组成数字一定有离它最近的斐波那契数字

时间复杂度:O(log n) 
空间复杂度:O(log n)

class Solution {
    public int findMinFibonacciNumbers(int k) {
        //如果 k 为 0,返回 0
        if(k == 0){
            return 0;
        }
        //定义当前值,上一值,辅助变量
        int cur = 1, pre = 1, temp = 2;
        //给数组赋值
        while(cur <= k){
            //计算新的值
            temp = cur + pre;
            //上一值变为当前值
            pre = cur;
            //当前值变为新的值
            cur = temp;
        }
        //k 减去上一值,继续递归遍历
        return findMinFibonacciNumbers(k - pre) + 1;
    }
}

方法2:贪心+迭代

因为 方法1 每次递归都要重复创建斐波那契数列,比较浪费时间,为避免这种情况,我们可以用迭代的方式。因为找斐波那契数列的时候我们定义了记录上一值的变量,那么我们可以反编译斐波那契数列,如果 k 的值大于当前数字,就减去当前数字,继续遍历,直到 k 为 0,然后返回减去的次数即可。

时间复杂度:O(log n) 
空间复杂度:O(log n)

class Solution {
    public int findMinFibonacciNumbers(int k) {
        //定义当前值,上一值,辅助变量
        int cur = 1, pre = 1, temp = 2;
        //给数组赋值
        while(cur <= k){
            //计算新的值
            temp = cur + pre;
            //上一值变为当前值
            pre = cur;
            //当前值变为新的值
            cur = temp;
        }
        //记录数目
        int count = 0;
        //反编译斐波那契数列
        while(k > 0){
            //当前数字小于等于 k,k 减去当前数字
            if(cur <= k){
               k -= cur;
               count++;
            }
            //计算上上一值
            temp = cur - pre;
            //当前值变为上一值
            cur = pre;
            //上一值变为上上一值
            pre = temp;
        }
        //返回计数结果
        return count;
    }
}

题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-the-minimum-number-of-fibonacci-numbers-whose-sum-is-k

标签:JAVA,数字,int,max,斐波,76,那契,Fn
来源: https://blog.csdn.net/qq_48772498/article/details/122778198

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有