[LintCode] Perfect Squares

方法一: 动态规划

https://segmentfault.com/a/1190000003768736

https://siddontang.gitbooks.io/leetcode-solution/content/dynamic_programming/perfect_squares.html

复杂度

时间 O(N^2) 空间 O(N)

思路

如果一个数x可以表示为一个任意数a加上一个平方数bxb,也就是x=a+bxb,那么能组成这个数x最少的平方数个数,就是能组成a最少的平方数个数加上1(因为b*b已经是平方数了)。

public class Solution {
    /**
     * @param n a positive integer
     * @return an integer
     */
    public int numSquares(int n) {
        // Write your code here
        int[] dp = new int[n + 1];
        // 将所有非平方数的结果置最大,保证之后比较的时候不被选中
        Arrays.fill(dp, Integer.MAX_VALUE);
        // 将所有平方数的结果置1
        for (int i = 0; i * i <= n; i++) {
            dp[i * i] = 1;
        }
        
        // 从小到大找任意数a
        for (int i = 0; i <= n; i++) {
            // 从小到大找平方数bxb
            for (int j = 1; i + j * j <= n; j++) {
                // 因为a+b*b可能本身就是平方数,所以我们要取两个中较小的
                dp[i + j * j] = Math.min(dp[i] + 1, dp[i + j * j]);    
            }
        }
        
        return dp[n];
    }
}

方法二:

数学 四平方和定理

https://www.cnblogs.com/grandyang/p/4800552.html

1) 所有的数字都可以用最多4个平方数的和表示。所以结果只可能是1,2,3,4

2) 进一步如果所有的数字可以整除4,就可以整除4,结果不会因此而改变。

3) 如果一个数除以8余7,那么该数字一定是由4个整数的平方相加组成的。

4)经过上述处理,剩下的数结果只可能是1,2,3。这个时候我们可以用试探这个整数是不是两个数或者一个数以及+0的和。是的话结果是1或者2。最后剩下的那些数就等于3.

public class Solution {
    /*
     * @param n: a positive integer
     * @return: An integer
     */
    public int numSquares(int n) {
        // write your code here
        while (n % 4 == 0) n /= 4;
        if (n % 8 == 7) return 4;
        for (int i = 0; i * i <= n; i++) {
            int j = (int)Math.sqrt(n * 1.0 - i * i);
            if (i * i + j * j == n) {
                if (i > 0 && j > 0) return 2;
                else return 1;
            }
        }
        return 3;
    }
}

 

 

 

动态规划

复杂度

时间 O(N^2) 空间 O(N)

思路

如果一个数x可以表示为一个任意数a加上一个平方数bxb,也就是x=a+bxb,那么能组成这个数x最少的平方数个数,就是能组成a最少的平方数个数加上1(因为b*b已经是平方数了)。

posted on 2017-05-25 12:15  codingEskimo  阅读(266)  评论(0编辑  收藏  举报

导航