[LeetCode] Perfect Squares 完全平方數
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
.
Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
又是超哥一個人辛苦的更新題目,一個人托起LeetCode免費題的一片天空啊,贊一個~ 這道題說是給我們一個正整數,求它最少能由幾個完全平方陣列成。這道題是考察四平方和定理,to be honest, 這是我第一次聽說這個定理,天啦擼,我的數學是語文老師教的麼?! 閒話不多扯,回來做題。先來看第一種很高效的方法,根據四平方和定理,任意一個正整數均可表示為4個整數的平方和,其實是可以表示為4個以內的平方數之和,那麼就是說返回結果只有1,2,3或4其中的一個,首先我們將數字化簡一下,由於一個數如果含有因子4,那麼我們可以把4都去掉,並不影響結果,比如2和8,3和12等等,返回的結果都相同,讀者可自行舉更多的栗子。還有一個可以化簡的地方就是,如果一個數除以8餘7的話,那麼肯定是由4個完全平方陣列成,這裡就不證明了,因為我也不會證明,讀者可自行舉例驗證。那麼做完兩步後,一個很大的數有可能就會變得很小了,大大減少了運算時間,下面我們就來嘗試的將其拆為兩個平方數之和,如果拆成功了那麼就會返回1或2,因為其中一個平方數可能為0. (注:由於輸入的n是正整數,所以不存在兩個平方數均為0的情況)。注意下面的!!a + !!b
解法一:
class Solution { public: int numSquares(int n) { while (n % 4 == 0) n /= 4; if (n % 8 == 7) return 4; for (int a = 0; a * a <= n; ++a) {int b = sqrt(n - a * a); if (a * a + b * b == n) { return !!a + !!b; } } return 3; } };
這道題遠不止這一種解法,我們還可以用動態規劃Dynamic Programming來做,我們建立一個長度為n+1的一維dp陣列,將第一個值初始化為0,其餘值都初始化為INT_MAX, i從0迴圈到n,j從1迴圈到i+j*j <= n的位置,然後每次更新dp[i+j*j]的值,動態更新dp陣列,其中dp[i]表示正整數i能少能由多個完全平方陣列成,那麼我們求n,就是返回dp[n]即可,也就是dp陣列的最後一個數字,參見程式碼如下:
解法二:
// DP class Solution { public: int numSquares(int n) { vector<int> dp(n + 1, INT_MAX); dp[0] = 0; for (int i = 0; i <= n; ++i) { for (int j = 1; i + j * j <= n; ++j) { dp[i + j * j] = min(dp[i + j * j], dp[i] + 1); } } return dp.back(); } };
下面再來看一種DP解法,這種解法跟上面有些不同,上面那種解法是初始化了整個長度為n+1的dp數字,但是初始化的順序不定的,而這個種方法只初始化了第一個值為0,那麼在迴圈裡計算,每次增加一個dp陣列的長度,裡面那個for迴圈一次迴圈結束就算好下一個數由幾個完全平方陣列成,直到增加到第n+1個,返回即可,想更直觀的看這兩種DP方法的區別,建議每次迴圈後都打印出dp數字的值來觀察其更新的順序,參見程式碼如下:
解法三:
// DP class Solution { public: int numSquares(int n) { vector<int> dp(1, 0); while (dp.size() <= n) { int m = dp.size(), val = INT_MAX; for (int i = 1; i * i <= m; ++i) { val = min(val, dp[m - i * i] + 1); } dp.push_back(val); } return dp.back(); } };
最後我們來介紹一種遞迴Recursion的解法,這種方法的好處是寫法簡潔,但是運算效率不敢恭維。我們的目的是遍歷所有比n小的完全平方數,然後對n與完全平方數的差值遞迴呼叫函式,目的是不斷更新最終結果,知道找到最小的那個,參見程式碼如下:
解法四:
// Recrusion class Solution { public: int numSquares(int n) { int res = n, num = 2; while (num * num <= n) { int a = n / (num * num), b = n % (num * num); res = min(res, a + numSquares(b)); ++num; } return res; } };
PS:解法二三四的運算效率真的不高,強推解法一,高效又易懂,如果想強行優化後三個演算法,可以將解法一的前兩個if判斷加到後三個的演算法的開頭,能很大的提高運算效率。
參考資料:
相關推薦
[LeetCode] Perfect Squares 完全平方數
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, r
(LeetCode 279)完全平方數 [簡單dp]
279. 完全平方數 給定正整數 n,找到若干個完全平方數(比如 1, 4, 9, 16, …)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。 示例 1: 輸入: n = 12 輸出: 3 解釋: 12 = 4 + 4 + 4. 示例 2: 輸入: n = 13
LeetCode 279. 完全平方數(Perfect Squares)
-a 題目 col min lee 狀態 res style turn 題目描述 給定正整數 n,找到若幹個完全平方數(比如 1, 4, 9, 16, ...)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。 示例 1: 輸入: n = 12 輸出: 3
[LeetCode] Valid Perfect Square 檢驗完全平方數
Given a positive integer num, write a function which returns True if num is a perfect square else False. Note: Do not use any built-in library function
[Swift]LeetCode279. 完全平方數 | Perfect Squares
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: Inp
279. Perfect Squares (完全平方數)
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, …) which sum to n. For exam
poj1730 - Perfect Pth Powers(完全平方數)(水題)
ostream splay -- size 技術 () isp close for /* 以前做的一道水題,再做精度控制又出了錯///。。。 */ 題目大意: 求最大完全平方數,一個數b(不超過int範圍),n=b^p,使得給定n,p最大; 題目給你一個數n,求p ; 解題
Leetcode 367. 有效的完全平方數 C++
題目: 給定一個正整數 num,編寫一個函式,如果 num 是一個完全平方數,則返回 True,否則返回 False。 說明:不要使用任何內建的庫函式,如 sqrt。 示例 1: 輸入:16 輸出:True 示例 2: 輸入:14 輸出:False 思路:
LeetCode學習記錄(3)----完全平方數
給定正整數 n,找到若干個完全平方數(比如 1, 4, 9, 16, ...)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。 示例 1: 輸入: n = 12 輸出: 3 解釋: 12 = 4 + 4 + 4. 示例 2: 輸入: n = 13 輸出:
[Leetcode]279.完全平方數
最開始的時候,我想到的動態方程很簡單,就是 dp[i]=min(dp[i],dp[i-平方數]+1) 其中i-平方數一定要大於0要不然就會越界。這個思路很簡單,舉個例子: dp[5]=min(dp[5-1^2]+1,dp[5-2^2]+1,dp[5]) 這表示5可以如下組合: dp[5] = min
Leetcode 279.完全平方數
完全平方數 給定正整數 n,找到若干個完全平方數(比如 1, 4, 9, 16, ...)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。 示例 1: 輸入: n = 12 輸出: 3 解釋: 12 = 4 + 4 + 4. 示例 2: 輸入
Leetcode 279:完全平方數(最詳細解決方案!!!)
給定正整數 n,找到若干個完全平方數(比如 1, 4, 9, 16, ...)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。 示例 1: 輸入: n = 12 輸出: 3 解釋: 12 = 4 + 4 + 4. 示例 2: 輸入: n = 13
Leetcode 367——有效的完全平方數(C++)
給定一個正整數 num,編寫一個函式,如果 num 是一個完全平方數,則返回 True,否則返回 False。注意:不要使用任何內建的庫函式,如 sqrt。示例 1:輸入: 16 輸出: True示例 2:輸入: 14 輸出: False老老實實的去遍歷的話會超時,故用
leetcode 367. 有效的完全平方數 python
給定一個正整數 num,編寫一個函式,如果 num 是一個完全平方數,則返回 True,否則返回 False。 說明:不要使用任何內建的庫函式,如 sqrt。 示例 1: 輸入:16 輸出:Tr
LeetCode刷題記錄——第367題(有效的完全平方數)
題目描述 給定一個正整數 num,編寫一個函式,如果 num 是一個完全平方數,則返回 True,否則返回 False。 說明:不要使用任何內建的庫函式,如 sqrt。 示例 1: 輸入:16 輸出:True 示例 2: 輸入:14 輸出:F
[leetcode]Python實現-367.有效的完全平方數
367.有效的完全平方數 描述 給定一個正整數 num,編寫一個函式,如果 num 是一個完全平方數,則返回 True,否則返回 False。 注意:不要使用任何內建的庫函式,如 sqrt。 示例 輸入: 16 輸出: True
Leetcode:279. 完全平方數
class Solution { public: int numSquares(int n) { return BFS(n); } int BFS(int n) { if (mp[n] > 0) { return
C++ LeetCode 完全平方數
題目要求: 給定正整數 n,找到若干個完全平方數(比如 1, 4, 9, 16, ...)使得它們的和等於 n。你需要讓組成和的完全平方數的個數最少。 示例 1: 輸入: n = 12 輸出: 3 解釋: 12 = 4 + 4 + 4. 示例 2: 輸入: n
LeetCode 279. 完全平方數 (C#實現)
blog span code 一個數 ++ 表示 res 動態 分享 問題:https://leetcode-cn.com/problems/perfect-squares/ GitHub實現:https://github.com/JonathanZxxxx/Lee
bzoj 2440 完全平方數
int close amp bsp play 莫比烏斯函數 題意 images ... 這是一道論文題。 題意:選出第k個無平方因子的數。 思路:二分答案。 某一個區間的無平方因子的數的個數怎麽求呢? 可以篩。 這裏可以莫比烏斯。 首先什麽是莫比烏斯函數呢?