diff --git a/Leecode/src/main/java/com/markilue/leecode/dynamic/T16_NumSquares.java b/Leecode/src/main/java/com/markilue/leecode/dynamic/T16_NumSquares.java new file mode 100644 index 0000000..6af6fde --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/dynamic/T16_NumSquares.java @@ -0,0 +1,95 @@ +package com.markilue.leecode.dynamic; + +import org.junit.Test; + +/** + * @BelongsProject: Leecode + * @BelongsPackage: com.markilue.leecode.dynamic + * @Author: markilue + * @CreateTime: 2022-12-07 10:49 + * @Description: + * TODO 力扣279题 完全平方数: + * 给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。 + * 完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。 + * @Version: 1.0 + */ +public class T16_NumSquares { + + @Test + public void test(){ + System.out.println(numSquares(12)); + } + + + /** + * 思路:这题与上一题零钱兑换是一个思路,区别在于这里没有给出coins数组 + * TODO 动态规划五部曲: + * (1)dp定义:dp[i][j]定义为使用[0-(i+1)^2]能凑出j所需要的最少数量 + * (2)dp状态转移方程:dp[j]=min(dp[j],dp[j-(i+1)^2+1]) 即使用(i+1)^2和不使用两种取最少 + * (3)dp初始化:dp[0]=0 最开始不需要硬币也能凑出dp + * (4)dp遍历顺序:与零钱兑换一样,两个for的顺序应该是不一样 + * (5)dp举例推导: + * 速度击败67.62%,内存击败41.23% 25ms + * @param n + * @return + */ + public int numSquares(int n) { + int max=n+1; //因为最少可以用1凑n,最多只需要n个数字 + int[] dp = new int[n+1]; + dp[0]=0; + for (int i = 1; i < max; i++) { + dp[i]=max; + } + int maxSqrt = (int)Math.sqrt(n); + + for (int i = 1; i <= maxSqrt; i++) { + for (int j = i*i; j < n + 1; j++) { + if(dp[j-i*i]!=max){ + dp[j]=Math.min(dp[j],dp[j-i*i]+1); + } + } + } + + return dp[n]; + + } + + + /** + * 官方提供的数学法:核心是利用数学规律得出当且有四种解法 + * 时间复杂度O(sqrt(n)) + * 速度击败100%,内存击败98.25% + * @param n + * @return + */ + public int numSquares1(int n) { + if (isPerfectSquare(n)) { + return 1; + } + if (checkAnswer4(n)) { + return 4; + } + for (int i = 1; i * i <= n; i++) { + int j = n - i * i; + if (isPerfectSquare(j)) { + return 2; + } + } + return 3; + } + + // 判断是否为完全平方数 + public boolean isPerfectSquare(int x) { + int y = (int) Math.sqrt(x); + return y * y == x; + } + + // 判断是否能表示为 4^k*(8m+7) + public boolean checkAnswer4(int x) { + while (x % 4 == 0) { + x /= 4; + } + return x % 8 == 7; + } + +}