[菜鸟训练]279. 完全平方数

题目描述:

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

示例 1:
输入:n = 12
输出:3
解释:12 = 4 + 4 + 4

示例 2:
输入:n = 13
输出:2
解释:13 = 4 + 9

提示:
1 <= n <= 104

解题思路:

方法一:dp,通过题目我们不难得出numSquares(n) = numSquares(n-k) + 1,其中k为完全平方数。这不就是我们所熟悉的状态转移方程么,接下来的工作就变成了该怎么用代码实现了。

代码:

    //方法一:dp,用来存储构成当前i值的完全平方数的最少数量
    //转移方程:numSquares(n) = numSquares(n - k) + 1,k为完全平方数
    //因为每次numSquares()找的都是数量最少的,所以得到的numSquares(n)也一定是数量最少的
    //效率不高,时间复杂度O(n^(3/2))  空间复杂度O(n)
    public int numSquares(int n) {
        //数组一定要开大一小点,养成习惯
        int[] dp = new int[n + 10];
        //将dp数组中的值都改为Integer所允许的最大值,方便接下来的min操作
        Arrays.fill(dp,Integer.MAX_VALUE);
        dp[0] = 0;//起始点
        for (int i = 1;i <= n; i++){
            for (int j = 1; j <= Math.sqrt(i);j++){
             	//枚举有可能的完全平方数j*j,找完全平方数数量最少
                if (i >= j*j )
                    dp[i] = Math.min(dp[i], dp[i - j * j] +1);
            }
        }
        return dp[n];
    }

方法二:数学定理,使用三平方数定理和四平方式定理.
四平方定理:也称作Bachet猜想,每个自然数都可以表示为4个整数平方和。
在这里插入图片描述

三平方定理:
在这里插入图片描述
其中k、m为整数。三平方定理说明了如果n=4k(8m+7)的话,那他就不能分解为三个平方数的和,所以此时它只能是4个平方数的和。所以当n满足以上条件时,我们就得到其最少可以由四个平方数的和组成。但不相等的话,我们不能断言它一定最少由三个平方数组成,因为他可能是由一个或者两个组成,所以我们需要在进行判断,判断它是否是完全平方数,是的话返回1。不是的话,通过枚举判断它是否是由两个平方数组成,是的话返回2。不是以上情况则满足三平方定理,返回3.

//方法二:数学定理,该题的最优解,时间复杂度O(n^1/2)  空间复杂度O(1)
    public int numSquares1(int n) {
        int num = n;
        //1.判断是否不满足三平方定理,不满足则一定是由四个完全平方数组成
        //即判断n与4^k(8m+7)的关系
        while (num % 4 == 0){
            num /= 4;
        }
        if (num % 8 == 7){
            return 4;
        }

        //2.判断该数是不是完全平方数,如果是则返回1
        int k = (int) Math.sqrt(n);
        if (k*k == n){
            return 1;
        }

        //3.只剩下由两个完全平方数组成的情况,没有定理,只能枚举
        for (int i = 1; i <= k;i++){
            int tmp = n - i*i;
            int t= (int) Math.sqrt(tmp);
            if (t*t == tmp){
                return 2;
            }
        }
        //4.其他情况都满足三平方数原则,返回3
        return 3;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值