# 279. 完全平方數
# https://leetcode-cn.com/problems/perfect-squares/
import math
import sys
class Solution_0:
"""
這道題目跟最長遞增子序列很相似,都是從當前位置查找之前的位置。
dp[i] = min( dp[i - j*j] + 1, dp[i] )
當前位置之前的元素,找個最小的 當前元素,由於是一個遍歷,該值一直是記錄之前最小的
類似於一個循環中查找最小值的邏輯
min_val = min(min_val, cur_val)
"""
def numSquares(self, n: int) -> int:
dp = [sys.maxsize for i in range(n + 1)]
# dp問題的初始設置很重要
dp[0] = 0
dp[1] = 1
for i in range(1, n + 1):
for j in range(1, int(math.sqrt(i)) + 1):
dp[i] = min(dp[i - j * j] + 1, dp[i])
return dp[n]
方法二 BFS
from queue import Queue
import math
class Solution:
def numSquares(self, n):
"""
BFS 需要進行剪枝,備忘錄法,如果已經計算過了,就不要再計算了
:param n:
:return:
"""
q = Queue()
q.put(n)
visited = set()
visited.add(n)
level = 1
while not q.empty():
# 遍歷每一層
for _ in range(q.qsize()):
node = q.get()
# 依次減去小於node的平方和,構造出下一層的值
for i in range(1, int(math.sqrt(node)) + 1):
tmp = node - i * i
# 如果已經計算過了, 就跳過
if tmp in visited:
continue
if tmp == 0:
return level
if tmp > 0:
q.put(tmp)
visited.add(tmp)
level = level + 1
return -1
if __name__ == '__main__':
sol = Solution()
res = sol.numSquares(7168)
print(res)