解法一:动态规划

找出小于等于n的所有完全平方数,然后就是一个背包问题。

  1. class Solution {
  2. public int numSquares(int n) {
  3. final int LEN = (int) Math.sqrt(n);
  4. int[] squareNumber = new int[LEN + 1];
  5. // squareNumber[i] = i*i
  6. for (int i = 1; i <= LEN; ++i) {
  7. squareNumber[i] = i * i;
  8. }
  9. // dp[i]表示i可以被分解成的最小完全平方和个数
  10. int[] dp = new int[n + 1];
  11. Arrays.fill(dp, Integer.MAX_VALUE);
  12. dp[0] = 0;
  13. for (int i = 1; i <= n; ++i) {
  14. for (int j = 1; j <= Math.sqrt(i); ++j) {
  15. dp[i] = Math.min(dp[i], dp[i - squareNumber[j]] + 1);
  16. }
  17. }
  18. return dp[n];
  19. }
  20. }

解法二:贪心+递归

参考:https://leetcode-cn.com/problems/perfect-squares/solution/wan-quan-ping-fang-shu-by-leetcode/

  1. class Solution {
  2. Set<Integer> squareNumber;
  3. public int numSquares(int n) {
  4. init(n);
  5. for (int i = 1; i <= n; ++i) {
  6. if (isDividedBy(n, i)) {
  7. return i;
  8. }
  9. }
  10. return -1;
  11. }
  12. private void init(int n) {
  13. squareNumber = new HashSet<>();
  14. for (int i = 1; i * i <= n; ++i) {
  15. squareNumber.add(i * i);
  16. }
  17. }
  18. /**
  19. * n能否被分解为count个完全平方数
  20. *
  21. * @param n
  22. * @param count
  23. * @return
  24. */
  25. private boolean isDividedBy(int n, int count) {
  26. if (count == 1) {
  27. return squareNumber.contains(n);
  28. }
  29. for (int sqr : squareNumber) {
  30. if (isDividedBy(n - sqr, count - 1)) {
  31. return true;
  32. }
  33. }
  34. return false;
  35. }
  36. }