Facebook Pixel

2507. Smallest Value After Replacing With Sum of Prime Factors

MediumMathNumber TheorySimulation
Leetcode Link

Problem Description

You start with a positive integer n. Your task is to repeatedly transform this number by replacing it with the sum of its prime factors until the number cannot be reduced further.

The transformation process works as follows:

  • Find all prime factors of n (including repeated factors)
  • Add up all these prime factors to get a new value
  • Replace n with this sum
  • Repeat this process

For example, if n = 12:

  • Prime factorization of 12 is 2 × 2 × 3
  • Sum of prime factors = 2 + 2 + 3 = 7
  • Now n becomes 7

Since 7 is already prime, it equals its own prime factor (7), so the sum would be 7 again. The process stops here.

The key points to remember:

  • If a prime factor appears multiple times in the factorization, it should be counted multiple times in the sum
  • Continue the replacement process until n stops changing (when n equals the sum of its prime factors)
  • Return the final smallest value that n becomes

The solution implements this by:

  1. Starting with the given number n
  2. Finding all prime factors by trial division starting from 2
  3. For each prime factor found, adding it to the sum and dividing n by it
  4. If after checking all factors up to √n, there's still a remainder greater than 1, that remainder is also a prime factor
  5. Checking if the sum equals the original number - if yes, returning it; otherwise, setting n to the sum and repeating
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is that when we replace a number with the sum of its prime factors, the number generally becomes smaller (except when the number is already prime). This is because for any composite number n, the sum of its prime factors is always less than n itself.

For example:

  • 12 = 2 × 2 × 3, and 2 + 2 + 3 = 7 < 12
  • 20 = 2 × 2 × 5, and 2 + 2 + 5 = 9 < 20

This property guarantees that the process will eventually converge to a fixed point - a number that equals the sum of its own prime factors. This happens when:

  1. The number is prime (a prime number p has only itself as a prime factor, so sum = p)
  2. The number is 4 (since 4 = 2 × 2, and 2 + 2 = 4)

Since we're continuously reducing the number (except at the fixed points), we can simply simulate the process until we reach a point where the number stops changing. We don't need any complex optimization because:

  • The number decreases rapidly with each iteration
  • Prime factorization using trial division up to √n is efficient enough for the reducing values
  • We can detect convergence by checking if the sum equals the original number before transformation

The trial division approach works well here because we only need to check divisors up to √n. Any factor larger than √n would have a corresponding factor smaller than √n, so if no small factor is found, the remaining number must be prime.

Learn more about Math patterns.

Solution Approach

The solution uses a brute force simulation approach with trial division for prime factorization. Here's how the implementation works:

Main Loop Structure: The algorithm uses an infinite while 1 loop that continues until we find the fixed point where the number equals the sum of its prime factors.

Prime Factorization Process: For each iteration, we:

  1. Store the current value of n in variable t for later comparison
  2. Initialize sum s = 0 to accumulate prime factors
  3. Start checking divisors from i = 2

Trial Division Algorithm: The core factorization uses trial division up to √n:

while i <= n // i:  # Equivalent to i <= sqrt(n)
    while n % i == 0:
        n //= i     # Remove factor i from n
        s += i      # Add factor to sum
    i += 1

This efficiently finds all prime factors by:

  • Checking each potential divisor i starting from 2
  • For each divisor that divides n, we repeatedly divide n by it and add it to the sum
  • This handles repeated prime factors correctly (e.g., for 12 = 2² × 3, we add 2 twice)

Handling Remaining Prime: After the trial division loop:

if n > 1:
    s += n

If n > 1 after checking all divisors up to √n, then n itself is a prime factor that needs to be added to the sum.

Convergence Check:

if s == t:
    return t
n = s

We check if the sum equals the original number. If yes, we've found our fixed point and return it. Otherwise, we set n to the sum and continue the process.

The algorithm is guaranteed to terminate because composite numbers always reduce to smaller values when replaced by the sum of their prime factors, eventually reaching a fixed point (either a prime number or 4).

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's trace through the algorithm with n = 24:

Iteration 1: n = 24

  • Store t = 24, initialize s = 0
  • Start trial division with i = 2:
    • 24 % 2 == 0, so n = 24/2 = 12, s = 0 + 2 = 2
    • 12 % 2 == 0, so n = 12/2 = 6, s = 2 + 2 = 4
    • 6 % 2 == 0, so n = 6/2 = 3, s = 4 + 2 = 6
    • 3 % 2 ≠ 0, increment i to 3
  • Continue with i = 3:
    • 3 % 3 == 0, so n = 3/3 = 1, s = 6 + 3 = 9
    • 1 % 3 ≠ 0, increment i to 4
  • Check i <= n//i: 4 <= 1//4 is false, exit loop
  • n = 1, not greater than 1, so don't add to sum
  • Check convergence: s = 9, t = 24, they're different
  • Set n = 9, continue

Iteration 2: n = 9

  • Store t = 9, initialize s = 0
  • Start trial division with i = 2:
    • 9 % 2 ≠ 0, increment i to 3
  • Continue with i = 3:
    • 9 % 3 == 0, so n = 9/3 = 3, s = 0 + 3 = 3
    • 3 % 3 == 0, so n = 3/3 = 1, s = 3 + 3 = 6
    • 1 % 3 ≠ 0, increment i to 4
  • Check i <= n//i: 4 <= 1//4 is false, exit loop
  • n = 1, not greater than 1, so don't add to sum
  • Check convergence: s = 6, t = 9, they're different
  • Set n = 6, continue

Iteration 3: n = 6

  • Store t = 6, initialize s = 0
  • Start trial division with i = 2:
    • 6 % 2 == 0, so n = 6/2 = 3, s = 0 + 2 = 2
    • 3 % 2 ≠ 0, increment i to 3
  • Check i <= n//i: 3 <= 3//3 is false (3 > 1), exit loop
  • n = 3 > 1, so s = 2 + 3 = 5
  • Check convergence: s = 5, t = 6, they're different
  • Set n = 5, continue

Iteration 4: n = 5

  • Store t = 5, initialize s = 0
  • Start trial division with i = 2:
    • 5 % 2 ≠ 0, increment i to 3
  • Check i <= n//i: 3 <= 5//3 is false (3 > 1), exit loop
  • n = 5 > 1, so s = 0 + 5 = 5
  • Check convergence: s = 5, t = 5, they're equal!
  • Return 5

The transformation sequence was: 24 → 9 → 6 → 5, and 5 is our answer since it's prime and equals the sum of its own prime factors.

Solution Implementation

1class Solution:
2    def smallestValue(self, n: int) -> int:
3        """
4        Find the smallest value by repeatedly replacing n with the sum of its prime factors
5        until n equals the sum of its prime factors (convergence point).
6        """
7        while True:
8            original_value = n
9            prime_factor_sum = 0
10            divisor = 2
11          
12            # Find all prime factors and calculate their sum
13            # Check divisors up to sqrt(n)
14            while divisor * divisor <= n:
15                # Extract all occurrences of current divisor
16                while n % divisor == 0:
17                    n //= divisor
18                    prime_factor_sum += divisor
19                divisor += 1
20          
21            # If n > 1 after factorization, n itself is a prime factor
22            if n > 1:
23                prime_factor_sum += n
24          
25            # Check if we've reached convergence (number equals sum of its prime factors)
26            if prime_factor_sum == original_value:
27                return original_value
28          
29            # Update n to the sum of prime factors for next iteration
30            n = prime_factor_sum
31
1class Solution {
2    public int smallestValue(int n) {
3        // Keep transforming n until we reach a fixed point
4        while (true) {
5            int originalValue = n;
6            int sumOfPrimeFactors = 0;
7          
8            // Find all prime factors and calculate their sum
9            // Check divisors from 2 up to sqrt(n)
10            for (int divisor = 2; divisor * divisor <= n; divisor++) {
11                // Extract all occurrences of current divisor
12                while (n % divisor == 0) {
13                    sumOfPrimeFactors += divisor;
14                    n /= divisor;
15                }
16            }
17          
18            // If n is still greater than 1, it's a prime factor itself
19            if (n > 1) {
20                sumOfPrimeFactors += n;
21            }
22          
23            // Check if we've reached a fixed point (sum equals original value)
24            if (sumOfPrimeFactors == originalValue) {
25                return sumOfPrimeFactors;
26            }
27          
28            // Update n to the sum for the next iteration
29            n = sumOfPrimeFactors;
30        }
31    }
32}
33
1class Solution {
2public:
3    int smallestValue(int n) {
4        // Keep transforming n until it cannot be reduced further
5        while (true) {
6            int originalValue = n;
7            int primeFactorSum = 0;
8          
9            // Find all prime factors and calculate their sum
10            // Check divisors up to sqrt(n) for efficiency
11            for (int divisor = 2; divisor * divisor <= n; ++divisor) {
12                // Extract all occurrences of current divisor
13                while (n % divisor == 0) {
14                    primeFactorSum += divisor;
15                    n /= divisor;
16                }
17            }
18          
19            // If n > 1 after factorization, n itself is a prime factor
20            if (n > 1) {
21                primeFactorSum += n;
22            }
23          
24            // If sum equals original value, we've found the smallest value
25            // (number is prime or cannot be reduced further)
26            if (primeFactorSum == originalValue) {
27                return primeFactorSum;
28            }
29          
30            // Update n to the sum of prime factors for next iteration
31            n = primeFactorSum;
32        }
33    }
34};
35
1function smallestValue(n: number): number {
2    // Keep transforming n until it cannot be reduced further
3    while (true) {
4        const originalValue = n;
5        let primeFactorSum = 0;
6      
7        // Find all prime factors and calculate their sum
8        // Check divisors up to sqrt(n) for efficiency
9        for (let divisor = 2; divisor * divisor <= n; divisor++) {
10            // Extract all occurrences of current divisor
11            while (n % divisor === 0) {
12                primeFactorSum += divisor;
13                n = Math.floor(n / divisor);
14            }
15        }
16      
17        // If n > 1 after factorization, n itself is a prime factor
18        if (n > 1) {
19            primeFactorSum += n;
20        }
21      
22        // If sum equals original value, we've found the smallest value
23        // (number is prime or cannot be reduced further)
24        if (primeFactorSum === originalValue) {
25            return primeFactorSum;
26        }
27      
28        // Update n to the sum of prime factors for next iteration
29        n = primeFactorSum;
30    }
31}
32

Time and Space Complexity

Time Complexity: O(√n × log n)

The algorithm repeatedly finds the sum of prime factors until the number cannot be reduced further. For each iteration:

  • The inner factorization loop runs in O(√n) time, as we check divisors up to √n
  • For each prime divisor i, we divide n by i repeatedly, which can happen at most log n times in total across all prime factors
  • The process continues until n equals the sum of its prime factors (convergence)
  • In the worst case, the number of iterations before convergence is O(log n) since each factorization typically reduces the value

Therefore, the overall time complexity is O(√n × log n).

Space Complexity: O(1)

The algorithm uses only a constant amount of extra space:

  • Variables t, s, and i for tracking the current value, sum, and iterator
  • No additional data structures are used
  • The space usage does not depend on the input size

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect Loop Termination Condition

A common mistake is using while divisor <= n instead of while divisor * divisor <= n for the trial division loop. This would cause unnecessary iterations and potential issues when n gets modified during factorization.

Wrong approach:

while divisor <= n:  # Incorrect - n changes during the loop!
    while n % divisor == 0:
        n //= divisor
        prime_factor_sum += divisor
    divisor += 1

Correct approach:

while divisor * divisor <= n:  # Correct - uses mathematical property
    while n % divisor == 0:
        n //= divisor
        prime_factor_sum += divisor
    divisor += 1

2. Forgetting to Handle the Remaining Prime Factor

After the trial division loop, if n > 1, then n itself is a prime factor. Forgetting this check will produce incorrect results for numbers with large prime factors.

Incomplete solution:

# Missing the check for remaining prime
while divisor * divisor <= n:
    while n % divisor == 0:
        n //= divisor
        prime_factor_sum += divisor
    divisor += 1
# Forgot: if n > 1: prime_factor_sum += n

3. Not Preserving the Original Value for Comparison

The algorithm modifies n during factorization, so we need to store the original value to check for convergence. Without this, the comparison will always fail.

Wrong implementation:

while True:
    prime_factor_sum = 0
    divisor = 2
    # Factorization modifies n...
    if prime_factor_sum == n:  # Wrong! n has been modified
        return n

Correct implementation:

while True:
    original_value = n  # Save original value
    prime_factor_sum = 0
    divisor = 2
    # Factorization...
    if prime_factor_sum == original_value:  # Compare with saved value
        return original_value

4. Starting Divisor from 1 Instead of 2

Starting the divisor from 1 would cause an infinite loop since every number is divisible by 1.

Incorrect:

divisor = 1  # Wrong starting point

Correct:

divisor = 2  # Smallest prime number

5. Using Inefficient Prime Checking

Some might try to check if each divisor is prime before using it, which adds unnecessary complexity and time.

Inefficient approach:

def is_prime(num):
    # Prime checking logic
  
for divisor in range(2, n):
    if is_prime(divisor) and n % divisor == 0:
        # Process

Efficient approach (as in solution): The trial division naturally handles this - composite numbers won't be divisors after their prime factors have already been removed.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Consider the classic dynamic programming of longest increasing subsequence:

Find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order.

For example, the length of LIS for [50, 3, 10, 7, 40, 80] is 4 and LIS is [3, 7, 40, 80].

What is the recurrence relation?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More