L4. Print all Prime Factors of a Number | Maths Playlist
This chapter explores how to efficiently find and print all prime factors of a given integer , transitioning from naive trial division to optimized square-root bounds and advanced factor-stripping techniques.
1. Problem Statement: What is a Prime Factor?
When given an integer , the goal is to output all unique prime numbers that divide evenly without leaving a remainder.
Real-Life Analogy
Mental Hook: Think of an industrial sorting facility receiving a massive batch item (like packages). The facility breaks the batch down using foundational component sizes (). These components cannot be broken down any further (prime numbers) and fit evenly into the total inventory.
-
Example 1 ():
- All divisors:
- Prime divisors (Prime Factors):
-
Example 2 (): Prime factors are
-
Example 3 (): Standard school factorization method:
CODE780 / 2 = 390 390 / 2 = 195 195 / 3 = 65 65 / 5 = 13 13 / 13 = 1Prime factors:
2. Approach 1: The Extreme Naive Approach
The most intuitive approach is to iterate through every number from to , check if it divides , and then verify whether that divisor is a prime number.
Pseudo-Code / Algorithm
vector<int> primeFactors;
for (int i = 2; i <= n; i++) {
if (n % i == 0) {
if (isPrime(i)) {
primeFactors.push_back(i);
}
}
}
Complexity Analysis
- Time Complexity: because the outer loop runs times, and the inner
isPrime()check takes time. - Space Complexity: where is the variable number of prime factors stored in the list.
3. Approach 2: Optimizing with Square Root Divisor Pairs
Building upon the divisor property from previous lectures, divisors always exist in pairs. If divides , then is also a divisor. Thus, we only need to loop up to .
Core Optimization Logic
Instead of checking all the way up to , we check up to and test both and .
vector<int> primeFactors;
for (int i = 1; i * i <= n; i++) {
if (n % i == 0) {
if (isPrime(i)) primeFactors.push_back(i);
if (i != n / i && isPrime(n / i)) primeFactors.push_back(n / i);
}
}
Complexity Analysis
- Time Complexity: Approximate , but non-deterministic because
isPrime()only triggers on actual factors. - Space Complexity: Variable space for storing the answer list.
4. Approach 3: School Method with Iterative Division (Stripping Factors)
We can completely eliminate the expensive isPrime() function by using a smart school-book approach: iteratively dividing out factors as we encounter them.
Step-by-Step Flow
Pseudo-Code
vector<int> primeFactors;
for (int i = 2; i <= n; i++) {
if (n % i == 0) {
primeFactors.push_back(i);
while (n % i == 0) {
n = n / i;
}
}
}
Limitations of Approach 3
- If given a large prime number like , the loop runs all the way from to .
- Worst-Case Time Complexity: when the number is a large prime.
5. Approach 4: The Highly Optimized Square-Root + Factor Stripping Algorithm
To fix the large prime bottleneck while keeping the speed of factor-stripping, we combine the loop limit with while-loop division and a final cleanup check.
Complete Optimized Algorithm
vector<int> primeFactors;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
primeFactors.push_back(i);
while (n % i == 0) {
n = n / i;
}
}
}
if (n != 1) {
primeFactors.push_back(n);
}
Dry Run Walkthrough ()
- : . Add
2. Reduce viawhileuntil . - : . Add
3. Reduce viawhileuntil . - : . Skip.
- : . Add
5. Reduce viawhileuntil . - Loop Termination: Next, . , which exceeds the remaining . The loop terminates.
- Final Check: Since remaining , add
13toprimeFactors. - Final Result:
[2, 3, 5, 13](Loop executed only up to instead of ).
6. Comparison of All Approaches
Summary and Key Takeaways
- Prime Factor Definition: Prime factors are divisors of a number that are themselves prime numbers (e.g., prime factors of are ).
- Avoid Redundant Prime Checks: Using an expensive
isPrime()function inside divisor loops degrades performance unnecessarily. - Factor Stripping Technique: Dividing repeatedly inside a
while (n % i == 0)loop ensures that composite multiples (like ) are automatically filtered out without extra checks. - Square Root Bound (
i * i <= n): Factors always exist in pairs around , limiting the search space drastically. - The Leftover Prime Check: When looping only up to , a large prime factor may remain uncaptured unless a final
if (n != 1)catch is executed. - Optimal Time Complexity: The best-case and average-case time complexity drops down to , making it extremely efficient even for large inputs.