以sqrt(n) 為時間復雜度的算法並不多見,最具代表性的就是分解質因數了。
235. 分解質因數
中文
English
將一個整數分解為若干質因數之乘積。
樣例
樣例 1:
輸入:10
輸出:[2, 5]
樣例 2:
輸入:660
輸出:[2, 2, 3, 5, 11]
注意事項
你需要從小到大排列質因子。
class Solution: """ @param num: An integer @return: an integer array """ def primeFactorization(self, num): # write your code here result = [] k = 2 while k*k <= num: if num % k == 0: num = num//k result.append(k) else: k += 1 if num > 1: result.append(num) return result
題目描述
http://www.lintcode.com/problem/prime-factorization/
具體步驟
- 記up=[n]up = [\sqrt{n}]up=[n
- ],作為質因數k的上界, 初始化k=2k=2k=2。
- 當k<=upk <= upk<=up 且 n不為1 時,執行步驟3,否則執行步驟4。
- 當n被k整除時,不斷整除並覆蓋n,同時結果中記錄k,直到n不能整出k為止。之后k自增,執行步驟2。
- 當n不為1時,把n也加入結果當中,算法結束。
幾點解釋
- 不需要判定k是否為質數,如果k不為質數,且能整出n時,n早被k的因數所除。故能整除n的k必是質數。
- 為何引入up?為了優化性能。當k大於up時,k已不可能整除n,除非k是n自身。也即為何步驟4判斷n是否為1,n不為1時必是比up大的質數。
- 步驟2中,也判定n是否為1,這也是為了性能,當n已為1時,可早停。
代碼
Java:
public List<Integer> primeFactorization(int n) { List<Integer> result = new ArrayList<>(); int up = (int) Math.sqrt(n); for (int k = 2; k <= up && n > 1; ++k) { while (n % k == 0) { n /= k; result.add(k); } } if (n > 1) { result.add(n); } return result; }
Python:
def primeFactorization(n): result = [] up = int(math.sqrt(n)); k = 2 while k <= up and n > 1: while n % k == 0: n //= k result.append(k) k += 1 if n > 1: result.append(n) return result
C++:
vector<int> primeFactorization(int n) { vector<int> result; int up = (int)sqrt(n); for (int k = 2; k <= up && n > 1; ++k) { while (n % k == 0) { n /= k; result.push_back(k); } } if (n > 1) { result.push_back(n); } return result; }
復雜度分析
- 最壞時間復雜度 O(n)O(\sqrt{n})O(n
- )。當n為質數時,取到其最壞時間復雜度。
- 空間復雜度 O(log(n))O(log(n))O(log(n)),當n質因數很多時,需要空間大,但總不會多於O(log(n))O(log(n))O(log(n))個。
延伸
質因數分解有一種更快的算法,叫做Pollard Rho快速因數分解。該算法時間復雜度為O(n1/4)O(n^{1/4})O(n1/4),其理解起來稍有難度,有興趣的同學可以進行自學,參考鏈接。