秋招 - 算法 - 完全平方数

114 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第25天,点击查看活动详情 >>

一、题目描述 LeetCode - 279

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
示例 1:

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

示例 2:

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

二、解题思路

本题要求计算出和为n的所需完全平方数的最少数量,我们可以考虑使用动态规划来解决。在使用动态规划时,考虑比n小的所有数,组成它们所需的完全平方数的最少数量,进而计算出组成n所需的完全平方数的最小数量。我们定义数组dp用来保存中间状态,其中dp[i]表示最少需要多少个完全平方数来组成数字i。而且这些数一定落在区间[1,i^1/2]之内,我们可以枚举这些数,假设当前枚举到j,则还需要完全平方数来构成i-j^2。此时我们可以设置状态转移方程为f[i]=1+min(f[i-j^2])(1<=j<=n^1/2)。经过此状态转移方程,我们可以完成数组dp最终dp[n]即为所求答案。

三、代码

class Solution {
    public int numSquares(int n) {
        int[] dp = new int[n+1];
        for (int i=1; i<=n; i++){
            int min = Integer.MAX_VALUE;
            for (int j=1; j*j<=i; j++){
                min = Math.min(min, dp[i-j*j]);
            }
            dp[i] = min + 1;
        }
        return dp[n];
    }
}

五、总结

本题使用动态规划求解,创建数组dp用来保存中间状态。其时间复杂度为O(n*n^1/2),n为给定的正整数,在我们计算状态转移方程时,由于仅需计算i的一半所以时间复杂度为O(n^1/2),但需要计算n个数所以是O(n*n^1/2)。空间复杂度为O(n),既数组dp的大小。