LeetCode 279. Perfect Squares

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.

Credits:

Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.


方法一:

class Solution {
public:
    int numSquares(int n) {
        
        assert(n > 0);
        
        queue< pair<int,int> > q;
        q.push(make_pair(n , 0));
        
        vector<bool> visited(n+1 , false);
        visited[n] = true;
        
        while (!q.empty())
        {
            int num = q.front().first;
            int step = q.front().second;
            q.pop();
            
            if (num == 0) return step;
            
            for (int i=0; num-i*i>=0; i++)
                if (!visited[num-i*i])
                {
                    q.push(make_pair(num-i*i , step+1));
                    visited[num-i*i] = true;
                }
        }
    }
};

方法二:

class Solution {
public:
    int numSquares(int n) {
        
        assert(n > 0);
        
        queue< pair<int,int> > q;
        q.push(make_pair(n , 0));
        
        vector<bool> visited(n+1 , false);
        visited[n] = true;
        
        while (!q.empty())
        {
            int num = q.front().first;
            int step = q.front().second;
            q.pop();
            
            
            for (int i=0; ; i++)
            {
                int a = num-i*i;
                if (a < 0) break;
                if (a == 0) return step+1;
                
                if (!visited[a])
                {
                    q.push(make_pair(a , step+1));
                    visited[a] = true;
                }
            }
        }
    }
};

方法二相对于方法一其实只是做了个优化而已,可以看出,在第一种方法中重复计算了太多次的num-i*i,我们可以只进行一次,在第二种方法中,我们把终止条件放在了方法体中,设立一个变量a=num-i*i,当a<0时,我们直接break掉就好,而且在推入队列的过程中,如果我们取得a==0的话,就已经可以返回这个结果了,结果为step+1,而不需要等到在循环中再次把这个0给取出,所以在第二种方法中我们把a==0这个判断提前。这样优化以后,我们再次在LeetCode上提交代码,第一种方法的运行时间为48ms,第二种方法的运行时间为16ms,基本上提升了3倍。

方法三:动态规划

class Solution {
public:
    int numSquares(int n) {
        
        assert(n > 0);
        vector<int> memo(n+1,INT_MAX);
        memo[0] = 0;
        for (int i=1; i<=n; i++)
            for (int j=1; i-j*j>=0; j++) {
                // j + (i-j)
                memo[i] = min(memo[i],memo[i-j*j]+1);
            }
        
        return memo[n];
    }
};
使用动态规划的方法,将n不断分割为完全平方数和n-这个完全平方数,自底向上算出从1到n每个数至少需要多少个完全平方数相加。


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值