问题描述:

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.

For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.


算法:

使用最接近n的平方数的平方根nearst进行标记。

构建数组array长度为n+1,将array[0]废置。

从1到n迭代array的index:

    如果index为nearst**2则array[index] = 1

    如果index为(nearst+1)**2则array[index] = 1且nearst+=1

    否则:寻找i从1 到nearst范围内的(array[(nearst-i)**2]+array[n-(nearst-i)**2])的最小值。

返回:return array[n]

时间复杂度:

O(n*sqrt(n)) 由于nearst 约等于 sqrt(n)

代码:

class Solution(object):
      
    def numSquares(self, n):
        """
        :type n: int
        :rtype: int
        """

        array = [10e6 for _ in range(n+1)]
        nearst = 1
        for num in range(1,n+1):
            if num == nearst*nearst:
                array[num] = 1
            elif num == (nearst+1)*(nearst+1):
                array[num] = 1
                nearst += 1
            else:
                temp = array[nearst**2]+array[num-nearst**2]
                for i in range(1,nearst):
                    if temp > array[(nearst-i)**2]+array[num-(nearst-i)**2]:
                        temp = array[(nearst-i)**2]+array[num-(nearst-i)**2]
                array[num] = temp
        return array[n]
但是结果超时,这段代码中可以使用缓存以及列表表达式的方法进行优化。优化的方式可以使用类变量也可以使用装饰器,这里使用类变量比较方便,因为所调用函数中没有出现递归调用,反而数组array的存在举足轻重。可以将array作为类变量。

优化:

class Solution(object):
    #600 tests 1160ms
    cache = [0]

    def numSquares(self, n):
        """
        :type n: int
        :rtype: int
        """
        cache = Solution.cache
        if n <= len(cache)-1:
            return cache[n]

        array = [10e6 for _ in range(n+1)]
        nearst = 1
        for num in range(1,n+1):
            if num == nearst*nearst:
                array[num] = 1
            elif num == (nearst+1)*(nearst+1):
                array[num] = 1
                nearst += 1
            else:
                array[num] = min([array[(nearst-i)**2]+array[num-(nearst-i)**2] for i in range(nearst)])
        length = len(cache)
        for i in range(length, len(array)):
            cache.append(array[i])

        return array[n]