279.完全平方數-python.md
阿新 • • 發佈:2019-01-01
題目
給定正整數 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