【刷题1】LeetCode 279. 完全平方数 java题解

看题解:我明白了 我是草履虫

题目

1.题目

在这里插入图片描述

2.方法一:动态规划

分析

在这里插入图片描述

代码

class Solution {
    public int numSquares(int n) {
        int ssize=(int)Math.sqrt(n)+1;
        int[] snums=new int[ssize];
        //snums存着每个数的平方数值
        for(int i=1;i<ssize;i++){
            snums[i]=i*i;
        }
        int[] dp=new int[n+1];
        //初始化dp数组每个值为极大值
        Arrays.fill(dp, Integer.MAX_VALUE);
        //n=0时,结果是0个平方数
        dp[0]=0;
        //1..n,逐个计算dp[i]
        for(int i=1;i<=n;i++){
            for(int j=1;j<ssize;j++){
                if(snums[j]>i){
                    break;dp[i]的更新结束了,因为后面的平方数大于所需
                }
                dp[i]=Math.min(dp[i],dp[i-snums[j]]+1);
            }
        }
        return dp[n];
    }
}

复杂度

时间复杂度:O(n* √n),在主步骤中,我们有一个嵌套循环,其中外部循环是 n次迭代,而内部循环最多需要 √n。
空间复杂度:O(n),使用了一个一维数组 dp。

结果

在这里插入图片描述

3.方法二:贪心枚举

分析

定义一个方法,is_divided_by(n, count),返回n是否能被分解为count个平方数。分解终止时,即count=1时,只需要检查一个数n是否是平方数(是否在平方数数组里)。
与方法一 一样,需要存储1…Math.sqrt(n)+1的平方数。由于只需要知道它是否在平方数数组里,用HashSet存储平方数能降低时间复杂度。

代码

class Solution {
    //创建存储平方数的数组   
    HashSet<Integer> set;

    public int numSquares(int n) {
        set=new HashSet<>();
        //平方数数组 初始化赋值
        int ssize=(int)Math.sqrt(n)+1;
        for(int i=1;i<=ssize;i++){
            set.add(i*i);
        }

        int count=1;
        for(count=1;count<=n;count++){
            //n能被拆分成count个平方数
            if(is_divided_by(n, count)){
                return count;
            }
        }

        return count;
    }

    boolean is_divided_by(int n,int count){
        //递归终止条件
        if(count==1){
            return set.contains(n);
        }

        for(Integer s:set){
            //
            if(is_divided_by(n-s,count-1)){
                return true;
            }
        }
        return false;
    }
}

复杂度

在这里插入图片描述

结果

在这里插入图片描述

4.方法三:贪心+BFS

好家伙 真学不动了 每题都不会 每题都多解 脑子是个好东西我也想有

分析

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

复杂度

在这里插入图片描述

代码

class Solution {
    public int numSquares(int n) {
        //存储平方数
        //这次必须是有序的,所以用ArrayList数组,我本来用Set解答错误
        ArrayList<Integer> square_nums=new ArrayList<>();
        for(int i=1;i*i<=n;i++){
            square_nums.add(i*i);
        }
        //队列
        HashSet<Integer> queue=new HashSet<>();
        //初始化队列
        queue.add(n);
        //计数
        int value=0;

        while(queue.size()>0){
            value++;
            HashSet<Integer> next_queue=new HashSet<>();
            for(Integer a:queue){
                for(Integer b:square_nums){
                    if(a<b){
                        break;
                    }
                    //队列中的数是平方数:已找到解,返回value
                    else if(a.equals(b)){
                        return value;
                    }
                    //队列中的数不是平方数:减去平方数,并加入下一轮队列
                    else{
                        next_queue.add(a-b);
                    }
                }
            }
            //迭代队列
            queue=next_queue;
        }
        return value;
        //其实根本走不到这一步,循环里一定返回了,所以这里返回啥都行
    }
}

结果

在这里插入图片描述

5.方法四:数学方法

四平方定理blablabla…略过
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值