跳转至

LC279 - 完全平方数

PerfectSquares.go
package DP

import "math"

func numSquares(n int) int {
    return numSquares2(n)
}

//func numSquares(n int) int {
//  // 1 <= n <= 10000
//  var f func(int, int) int
//  f = func(index, rest int) int {
//      if index == 0 {
//          if rest == 0 {
//              return 0
//          } else {
//              return math.MaxInt
//          }
//      }
//      cur := index * index
//      if rest < cur {
//          return f(index-1, rest)
//      } else {
//          return min(f(index, rest-cur)+1, f(index-1, rest))
//      }
//  }
//  return f(100, n)
//}

// 二维DP
// 时间复杂度: O(n * √n), 空间复杂度: O(n * √n)
func numSquares1(n int) int {
    // 1 <= n <= 10000
    // dp[i][j] -> dp[i-1][j], dp[i][j-x]
    dp := make([][]int, 101)
    for i := 0; i < len(dp); i++ {
        dp[i] = make([]int, n+1)
    }
    for j := 1; j <= n; j++ {
        dp[0][j] = math.MaxInt
    }
    for i := 1; i <= 100; i++ {
        for j := 1; j <= n; j++ {
            cur := i * i
            if j < cur {
                dp[i][j] = dp[i-1][j]
            } else {
                dp[i][j] = min(dp[i-1][j], dp[i][j-cur]+1)
            }
        }
    }
    return dp[100][n]
}

// 一维DP
// 时间复杂度: O(n * √n), 空间复杂度: O(n)
func numSquares2(n int) int {
    // dp[i] = min(dp[i], dp[i-j*j]+1)
    dp := make([]int, n+1)
    for i := 1; i <= n; i++ {
        dp[i] = math.MaxInt
    }
    for i := 1; i <= n; i++ {
        for j := 1; j*j <= i; j++ {
            dp[i] = min(dp[i], dp[i-j*j]+1)
        }
    }
    return dp[n]
}

比较容易想到的方法是二维动态规划(numSquares1),但最优解是一维动态规划(numSquares2)。