1. 程式人生 > >279.完全平方數-python.md

279.完全平方數-python.md

題目

給定正整數 n,找到若干個完全平方數(比如 1, 4, 9, 16, …)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。

示例:

示例 1:

輸入: n = 12
輸出: 3 
解釋: 12 = 4 + 4 + 4.
示例 2:

輸入: n = 13
輸出: 2
解釋: 13 = 4 + 9.
解法一:

      利用佇列和廣度優先遍歷的方法,佇列以[(當前節點的值,步數)]的方式存,利用廣度優先遍歷最先到終點的路線一定是最短路徑的特點,來找到最短步數。

示例
class Solution:
    def numSquares(self, n):
        """
        :type n: int
        :rtype: int
        """
q = list() # 建立佇列 q.append([n, 0]) visited = [False for _ in range(n + 1)] # 儲存遍歷過的結點 visited[n] = True # 遍歷佇列裡的節點 while any(q): num, step = q.pop(0) i = 1 tnum = num - i ** 2 while tnum >=
0: # 最先到達0的一定是步數最少的 if tnum == 0: return step + 1 # 只新增沒有遍歷過的節點 if not visited[tnum]: q.append((tnum, step + 1)) visited[tnum] = True i += 1 tnum =
num - i ** 2
執行結果

執行結果

解法二:

      這種解法是在網上看到的,利用四平方和定理

Lagrange 四平方定理: 任何一個正整數都可以表示成不超過四個整數的平方之和。
那麼我們這個問題的解法就變得很簡單了,我們的結果只有1,2,3,4,四種可能。

另外還有一個非常重要的推論

if and only if n is not of the form n=4a(8b+7)n=4a(8b+7) for integers a and b.
滿足四數平方和定理的數n(這裡要滿足由四個數構成,小於四個不行),必定滿足 n=4a(8b+7)

我們首先將輸入的n迅速縮小。然後我們再判斷,這個縮小後的數是否可以通過兩個平方數的和或一個平方陣列成,不能的話我們返回3,能的話我們返回平方數的個數。
現在我們的問題已經縮減到了,怎麼判斷一個數是由一個還是由兩個平方數的和構成?對於這個問題,我們當然可以暴力破解。

示例
class Solution:
    def numSquares(self, n):
        """
        :type n: int
        :rtype: int
        """
        while n % 4 == 0:
            n /= 4

        if n % 8 == 7:
            return 4

        a = 0
        while a ** 2 <= n:
            b = int((n - a ** 2) ** 0.5)
            if a ** 2 + b ** 2 == n:
                return (not not a) + (not not b)

            a += 1

        return 3
執行結果

方式二執行結果