zoukankan      html  css  js  c++  java
  • [LeetCode] 279. Perfect Squares(完全平方数)

    Description

    Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.
    给定一个正整数 n,现需要用完全平方数(1, 4, 9, 16)的和凑出 n,问所需平方数的最小值。

    Examples

    Example 1

    Input: n = 12
    Output: 3 
    Explanation: 12 = 4 + 4 + 4.
    

    Example 2

    Input: n = 13
    Output: 2
    Explanation: 13 = 4 + 9.
    

    Solution

    先给出一个 naive 的做法,暴力搜索,大致基于下式进行计算(将题目所求的函数记为 (f(n))):

    [f(n) = egin{cases} 1& n 是完全平方数\ min(f(i) + f(n - i)) ; { i in [1, n / 2] } & else end{cases} ]

    为了防止重复计算,还是采用了记忆化搜索的方法,结果华丽丽的 TLE 了(input = 6175),而我本地跑这组测试数据的时候直接爆栈了……

    import kotlin.math.floor
    import kotlin.math.min
    import kotlin.math.sqrt
    
    class Solution {
        private val memo = hashMapOf<Int, Int>()
    
        fun numSquares(n: Int): Int {
            if (memo.containsKey(n)) {
                return memo.getValue(n)
            }
            if (n.isPerfectSquare()) {
                memo[n] = 1
                return 1
            }
            var result = Int.MAX_VALUE
            for (i in 1..(n / 2)) {
                result = min(result, numSquares(i) + numSquares(n - i))
            }
            memo[n] = result
            return result
        }
    
        private fun Int.isPerfectSquare(): Boolean {
            val root = floor(sqrt(this.toDouble())).toInt()
            return root * root == this
        }
    }
    

    自然只能找其它解法了,以下一个解法来自 discussion。考虑以下等式(还是一样,将原函数记为 (f(n))):

    [f(0) = 0 \ f(1) = f(0) + 1 = 1 \ f(2) = f(1) + 1 = 2 \ f(3) = f(2) + 1 = 3 \ f(4) = min(f(4 - 1 imes 1) + 1, f(4 - 2 imes 2) + 1) = min(f(3) + 1, f(0) + 1) = 1 \ f(5) = min(f(5 - 1 imes 1) + 1, f(5 - 2 imes 2) + 1) = min(f(4) + 1, f(1) + 1) = 2 \ ... \ f(13) = min(f(13 - 1 imes 1) + 1, f(13 - 2 imes 2) + 1, f(13 - 3 imes 3) + 1) = min(f(12) + 1, f(9) + 1, f(4) + 1) = 2 ]

    所以最后的状态转移方程是:

    [f(n) = min(f(n - i imes i) + 1)(其中 n - i imes i geq 0 且 i geq 1) ]

    代码如下:

    import kotlin.math.min
    
    class Solution {
        fun numSquares(n: Int): Int {
            val dp = IntArray(n + 1) { Int.MAX_VALUE }
            dp[0] = 0
            for (i in 1..n) {
                var min = Int.MAX_VALUE
                var j = 1
                while (i - j * j >= 0) {
                    min = min(min, dp[i - j * j] + 1)
                    j++
                }
                dp[i] = min
            }
            return dp.last()
        }
    }
    
  • 相关阅读:
    React Native 架构演进
    React Native 架构一览
    React Native 在 Airbnb 的起起落落
    React Native简史
    图解云服务模型的演进
    伯克利研究员们眼中的Cloud Computing
    彻底理解 IaaS、PaaS、SaaS
    JS更随机的随机数
    JS自动化
    fingerprint2 计算浏览器指纹分析
  • 原文地址:https://www.cnblogs.com/zhongju/p/13992706.html
Copyright © 2011-2022 走看看