1. 程式人生 > >Leetcode 279 完美平方數

Leetcode 279 完美平方數

Type: Medium, BFS

完美平方數

題目描述:

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

Example 1:

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

Example 2:

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

這裡還牽涉到一個理論是:四平方和定理。

每個正整數均可表示為4個整數平方和。

所以,本題的答案只在1,2,3,4這四個裡面了。

去驗證下:

139 / 588 test cases passed.

這個能過139個測試樣例的寫法是:

import random
class Solution:
    def numSquares(self, n):
        """
        :type n: int
        :rtype: int
        """
        return random.randint(1,4)

隨機1,2,3,4.

再測試只隨機輸出1,2,3,結果:

160 / 588 test cases passed.

還有提高哈。

嚴肅說明:這不是解題的正確態度,只是探索一下。

實際上,結合一個推論:

滿足四數平方和定理的數n(這裡要滿足由四個數構成,小於四個不行),必定滿足 n=4a(8b+7)n=4^a(8b+7)

可以知道,是四個整陣列成的,比較特殊。

import random
class Solution:
    def numSquares(self, n):
        """
        :type n: int
        :rtype: int
        """
        # 根據推論,降低問題規模:4^a(8b + 7)
        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

根據推論,4本身是平方數,所以可以不斷除以4,得到的8b + 7假定是a2+b2a^2 + b^2,帶上4可以看成是(2a)2+2(b)2(2a)^2 + 2(b)^2

縮減到只剩下8b+7後,就可以進行判斷是否滿足推論,否則開始暴力搜尋,滿足兩個完全平方數的 ,則輸出2,否則就是3.

DP解法

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

        # dp解法
        dp = [1e31] * (n + 1)
        a = int(n ** 0.5)
        for i in range(a + 1):
            dp[i * i] = 1
        for i in range(1,n + 1):
            b = int((n - i) ** 0.5) + 1
            for j in range(1,b):
                dp[i + j * j] = min(dp[i] + 1, dp[i + j * j])
                
        return dp[n]

END.