279. Perfect Squares

最后更新

三刷
16-Jan-2017

数学题= = 加一点点动态规划。

dp[n]表示 N能分成的最小数量。。

然后无非就是看一个数怎么分= =拿12来说:
9+3 1 + dp[3]
...
4+8 1 + dp[8]
...
1+11 1 + dp[11]

看哪个最少就是哪个分完就保存一下,以后再利用。

Time: O(n²)
Space: O(n)

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

一刷

给个N,计算N最少能由几个平方数组成

12 = 4 + 4 + 4 3个
13 = 4 + 9 2个

用DP来做

DP[N]代表 N最少由几个平方数组成

先看 N - M² > 0 ?
代表 DP[N]的值 = DP[N - M²] + 1
其中+1的1代表 最后要+的一个平方数M²
(N - M²) + M² = N
DP[N-M²]在1 TO N的过程中已经计算了

然后我们M+1
看看N是否可以减去一个更大的平方数

如果N - (M+1)² > 0
代表 DP[N]的值 = DP[N-(M+1)] + 1

但是我们不确定DP[N-(M+1)²]和DP[N-M²]谁大

所以要记录一个TEMP值 保留最小

public class Solution {
    public int numSquares(int n) {
 
    	int[] dp = new int[n+1];
    	dp[0] = 0;

    	for(int m = 1; m <= n;m++)
    	{	

    		dp[m] = Integer.MAX_VALUE;
    		//n - 1*1 > 0?
    		//n - 2*2 > 0?
    		//n - 3*3 > 0?
    		for(int t = 1; (m - t*t)>=0;t++)
    		{
    			dp[m] = Math.min(dp[m],dp[m-t*t]+1);
    		}
    		//System.out.println(dp[m]);
    		
    	}


    	return dp[n];

    }
}



二刷依然一头雾水,这个jianchao.li.fighter的题普遍数学味很大,头痛啊。。

public class Solution {
    public int numSquares(int n) 
    {
        
        /*
        1       1
        2       1 1 
        3       1 1 1
        4       2 2
        5       4 1
        6       4 1 1
        7       4 1 1 1
        8       4 4
        9       9
        10      9 1
        11      9 1 1
        12      4 4 4
        13      9 4
        */
        
        int[] dp = new int[n+1];
        
        dp[0] = 0;
        
        for(int i = 1; i <= n; i++)
        {
            dp[i] = Integer.MAX_VALUE;
            for(int t = 1; t*t <= i;t++)
            {
                dp[i] = Math.min(dp[i],dp[i-t*t]+1);
            }
        }
        
        return dp[n];
        
    }
}

其实说白了就是分解一个int为所有平方的和,怎么分数量最少。

在一开始分解的过程中就看出来了,12我分的是9+1+1+1 总共4个
而结果是 4+4+4 总共3个

暴力法就是 所有可能性都试一次,比如先从最大的平方和分:
9 1 1 1
4 4 4
4 4 1 1 1 1
4 1 1 1 1 1 1 1 1 1
这种,有很多重复计算。想办法减少重复计算。那么就是DP了。
dp[n]表示分解n的最优解。

dp[i] = Math.min(dp[i],dp[i-t*t]+1);

这样刚才的暴力分解就变成了个
9+3 1 + dp[3]
4+8 1 + dp[8]
1+11 1 + dp[11]

省去了很多重复计算。

原文地址:https://www.cnblogs.com/reboot329/p/6291624.html