279. Perfect Squares(DP or BFS)

一、题目描述

简单的DP,转化问题为BFS问题

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, …) which sum to n.

For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.

二,算法与代码

DP解法:只要发现对于非平方数(例如:2,3,5,6),它们的最小组成一定是由n个平方数和m个非平方数组成,而非平方数其实都只能由N个1组成,如2 = 1+ 1, 3 = 1 + 1 + 1。所以得到转移方程

dp[i]=min(dp[i],1+dp[ijj])

class Solution {
public:
    int numSquares(int n) {
        int res;
        vector<int> dp(n+1, 0);

        for(int i = 1; i <= n; i++) {
            dp[i] = i+1;
            for(int j = 1; j <= sqrt(i); j++) {
                dp[i] = min(dp[i], 1+dp[i - j*j]);
            }
        }
        return dp[n];

    }
};

BFS解法:如图所示,BFS的解法是先找出原始的小于n的所有平方数(allNs),以此作为第二层结点,通过与allNs中的平方数进行组合,找出可能的其他所有的小于n的结点,不断向外辐射这棵树,直到找到一条路径上的结点的数的和等于n,此时该路径上的数即为n的最小的平方数的组成,数的层数即为所求的最小数。

这里写图片描述

class Solution {
public:
   int numSquares(int n) {
        if(n <= 0) return 0;
        vector<int> squareNumber, countsOfnumSquares(n+1,0);
        for(int i = 0; i*i <= n; i++) {
            squareNumber.push_back(i*i);  //平方数 
            countsOfnumSquares[i*i] = 1;//n平方数的 numSquares 为1 
            if(i*i == n) return 1;
        }

        queue<int> tmp;
        for(int i = 0; i < squareNumber.size(); i++)
            tmp.push(squareNumber[i]);

        int count = 1;
        while(!tmp.empty()) {
            count++;
            for(int k = 0, size = tmp.size(); k < size; k++) {
                int cur = tmp.front();
                for(int i = 0; i < squareNumber.size(); i++) {
                    if(cur + squareNumber[i] == n) {
                        return count;
                    } else if(cur + squareNumber[i] < n && countsOfnumSquares[cur+squareNumber[i]] == 0) {
                        countsOfnumSquares[cur+squareNumber[i]] = count;
                        tmp.push(cur + squareNumber[i]);
                    } else if(cur + squareNumber[i] > n) {
                        break;
                    }   
                }
                tmp.pop();  
            }
        }
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值