Week14 Perfect Squares

Week14

Dynamic Programming
question source: 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.

question description

Example 1 :

Input: n = 12
Output: 3
Explanation: 12 = 4 + 4 + 4.

Example 2:

Input: n = 13
Output: 2
Explanation: 13 = 4 + 9

解决方法

题目是说判断一个数能最少用多少个平方数之和表示出来。这道题的标签是DP问题。本来想是否能用贪心算法表示出来,先将这个数分割成最大的平方数和另一个数,然后在另一个数中重复这个做法。但是很快就能看出一个反例。12 = 9 + 1 + 1 + 1需要4个,而最少其实是12 = 4 +4+4。然后就想用动态规划来解决了。
先定义子问题,num[i]定义为i这个数能最小多少个平方数之各和来表示。则问题的解为num[n]。

n u m [ i ] = m i n { n u m [ i − j ∗ j ] + 1 , i > = j ∗ j } num[i] = min \{num[i - j * j] + 1, i >= j * j\} num[i]=min{num[ijj]+1,i>=jj}
然后定义开始值。要多一个额外的量num[0]为0, nums[1]为1。

class Solution {
public:
    int numSquares(int n) {
        int num[n + 1];
        num[0] = 0;
        num[1] = 1;
        for(int i = 2; i <= n; i++){
            int min = i;
            for(int j = 2; j * j <= i; j++){
                if(min > num[i - j * j] + 1){
                    min = num[i - j * j] + 1;
                }
            }
            num[i] = min;
        }
        return num[n];
    }
};

算法复杂度是 O ( n l o g n ) O(nlogn) O(nlogn)

这题的另一个标签为Math,所以是可以通过数学方法来解决了。有一个定理叫四平方和定理,每一个正整数均可表示4个整数的平方和。还有一个Legendre’s three-square theorem,是说一个自然数能被表示为三个平方之和当且仅当它不符合 n = 4 a ( 8 ∗ b + 7 ) n = 4^a(8 * b + 7) n=4a(8b+7),a和b是整数。因此可以用这些数学定理来解决。首先判断这个数是否是某个数的平方,如果是,则返回1。其次,再判断能否分为2个数之和,如果是,则返回2,再判断是否是否符合前面的表达式,如果是,则返回4,否则返回3。

class Solution {
public:
    bool isSquare(int n){
        int sqr = floor(sqrt(n));
        return sqr * sqr == n;
    }
    int numSquares(int n) {
        if(isSquare(n)){
            return 1;
        }
        
        for(int i = 1; i * i < n; i++){
            if(isSquare(n - i * i)){
                return 2;
            }
        }
        
        int a = 1;
        while(n % (4 * a) == 0){
            a *= 4;
        }
        if((n / a) % 8 == 7){
            return 4;
        }
        
        return 3;
    }
};

是真的快,数学真的厉害啊!果然很多搞计算机的人才数学都不差。这个算法复杂度是 O ( l o g n ) O(logn) O(logn)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值