完全平方数

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

思路一:动态规划
本来我也是自己在想动态规划的做法,有思路了,可是过于复杂。在写代码的时候就在想,动态规划不是都挺短的代码吗,怎么我的逻辑这么长,会不会是我错了。看了看题解,发现确实是错了(倒也没错,就是太复杂,没找对正确的状态方程)。

  • 首先初始化长度为n+1的数组dp,每个位置都为0
  • 如果n为0,则结果为0
  • 对数组进行遍历,下标为i,每次都将当前数字先更新为最大的结果,即dp[i]=i,比如i=4,最坏结果为4=1+1+1+1即为4个数字
  • 动态转移方程为:dp[i] = MIN(dp[i], dp[i - j * j] + 1),i表示当前数字,jj表示平方数(加上的1,就是jj的情况)。任何一个数,都会被另一个数加上一个完全平方数而得到

时间复杂度:O(n*sqrt(n)),sqrt为平方根

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

思路二:广度优先遍历
当看到便签有广度优先遍历,我是很懵的。这既不是个图,又不是个数,怎么广度优先遍历?
直到在题解中看了这位老哥的图我才明白:

思想和动态规划相仿,都是表示成多种情况的完全平方数之和。最先一层出现0的就是最终结果。

class Solution {
    public int numSquares(int n) {
        Queue<Integer> queue = new LinkedList<Integer>();
        
        boolean[] visit = new boolean[n+1];   //标志是否被访问
        for(boolean v:visit) v = false;
        visit[n] = true;

        queue.offer(n);
        int res = 0;
        while(!queue.isEmpty()){
            res++;
            int length = queue.size();
            for(int i=0;i<length;i++){
                int num = queue.poll();
                for(int j=1;num-j*j>=0;j++){
                    if(num-j*j==0)  return res;
                    if(!visit[num-j*j]){
                        queue.offer(num-j*j);
                        visit[num-j*j] = true;
                    }
                    
                }
            }
        }
        return res;
    }
}
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值