• 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]

    省去了很多重复计算。

  • 相关阅读:
    javascirpt Scoket
    黑马程序员面试题(一)交通灯管理系统
    中软国际实习总结
    黑马程序员Java基础正则表达式
    黑马程序员Java基础加强Java高新技术
    黑马程序员JAVA基础GUI
    面试题(二)银行业务调度系统
    黑马程序员JAVA基础IO流之File 类
    黑马程序员JAVA基础IO流其他类
    黑马程序员Java基础网络编程
  • 原文地址:https://www.cnblogs.com/reboot329/p/6291624.html
Copyright © 2020-2023  润新知