Facebook Pixel

2427. Number of Common Factors

EasyMathEnumerationNumber Theory
Leetcode Link

Problem Description

You are given two positive integers a and b. Your task is to find and return the total number of common factors that both numbers share.

A common factor is defined as an integer x that can divide both a and b without leaving a remainder. In other words, x is a common factor if both a % x == 0 and b % x == 0.

For example, if a = 12 and b = 18:

  • The factors of 12 are: 1, 2, 3, 4, 6, 12
  • The factors of 18 are: 1, 2, 3, 6, 9, 18
  • The common factors are: 1, 2, 3, 6
  • So the answer would be 4

The solution works by first finding the greatest common divisor (GCD) of a and b. Since any common factor of two numbers must also be a factor of their GCD, we only need to count the factors of the GCD. The code iterates through all numbers from 1 to the GCD and counts how many of them divide the GCD evenly.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is recognizing that every common factor of two numbers must also be a factor of their greatest common divisor (GCD). This is because the GCD is the largest number that divides both a and b, and it contains all the common prime factors of both numbers.

To understand why this works, consider that if a number x divides both a and b, then x must also divide gcd(a, b). This is a fundamental property of GCD - it's essentially the "product" of all common factors at their minimum powers.

For example, if a = 12 and b = 18:

  • 12 = 2² × 3
  • 18 = 2 × 3²
  • gcd(12, 18) = 2 × 3 = 6

Any common factor must be formed from the shared prime factors (2 and 3 in this case), and all such combinations are exactly the factors of the GCD.

Therefore, instead of checking every number from 1 to min(a, b) to see if it divides both a and b, we can simplify the problem to just finding all factors of gcd(a, b). This reduces our search space significantly and makes the solution more efficient.

Once we have the GCD, we simply count how many numbers from 1 to GCD divide it evenly - these are exactly the common factors we're looking for.

Learn more about Math patterns.

Solution Approach

The implementation follows a straightforward enumeration approach after calculating the greatest common divisor:

Step 1: Calculate the GCD

  • Use Python's built-in gcd function from the math module to find g = gcd(a, b)
  • This gives us the greatest common divisor of the two numbers

Step 2: Count the factors of the GCD

  • Iterate through all numbers from 1 to g (inclusive)
  • For each number x in this range, check if it divides g evenly using the modulo operator: g % x == 0
  • If the remainder is 0, then x is a factor of g, which means it's also a common factor of a and b

Implementation Details:

  • The solution uses a generator expression with sum() to count the factors efficiently: sum(g % x == 0 for x in range(1, g + 1))
  • The expression g % x == 0 evaluates to True (counted as 1) when x is a factor, and False (counted as 0) otherwise
  • By summing these boolean values, we get the total count of common factors

Time Complexity: O(g) where g is the GCD of a and b. In the worst case, this is O(min(a, b)).

Space Complexity: O(1) as we only use a constant amount of extra space.

The elegance of this solution lies in reducing the problem from checking divisibility for both numbers to just checking divisibility for their GCD, which significantly simplifies the logic while maintaining correctness.

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 walk through the solution with a = 24 and b = 36.

Step 1: Find the GCD

  • First, we calculate gcd(24, 36)
  • Using the Euclidean algorithm:
    • 36 = 24 × 1 + 12
    • 24 = 12 × 2 + 0
  • So gcd(24, 36) = 12

Step 2: Find all factors of the GCD (12)

  • Now we check each number from 1 to 12:
    • 12 % 1 = 0 ✓ (1 is a factor)
    • 12 % 2 = 0 ✓ (2 is a factor)
    • 12 % 3 = 0 ✓ (3 is a factor)
    • 12 % 4 = 0 ✓ (4 is a factor)
    • 12 % 5 = 2 ✗ (5 is not a factor)
    • 12 % 6 = 0 ✓ (6 is a factor)
    • 12 % 7 = 5 ✗ (7 is not a factor)
    • 12 % 8 = 4 ✗ (8 is not a factor)
    • 12 % 9 = 3 ✗ (9 is not a factor)
    • 12 % 10 = 2 ✗ (10 is not a factor)
    • 12 % 11 = 1 ✗ (11 is not a factor)
    • 12 % 12 = 0 ✓ (12 is a factor)

Step 3: Count the factors

  • The factors of 12 are: 1, 2, 3, 4, 6, 12
  • Total count = 6

Verification: These are indeed the common factors of 24 and 36:

  • 24 = 1×24 = 2×12 = 3×8 = 4×6 (divisible by 1, 2, 3, 4, 6, 12)
  • 36 = 1×36 = 2×18 = 3×12 = 4×9 = 6×6 (divisible by 1, 2, 3, 4, 6, 12)

Therefore, the answer is 6 common factors.

Solution Implementation

1from math import gcd
2
3class Solution:
4    def commonFactors(self, a: int, b: int) -> int:
5        # Find the greatest common divisor of a and b
6        # All common factors of a and b must be factors of their GCD
7        greatest_common_divisor = gcd(a, b)
8      
9        # Count how many numbers from 1 to GCD divide the GCD evenly
10        # These are all the common factors of a and b
11        factor_count = sum(
12            greatest_common_divisor % divisor == 0 
13            for divisor in range(1, greatest_common_divisor + 1)
14        )
15      
16        return factor_count
17
1class Solution {
2    /**
3     * Counts the number of common factors between two integers.
4     * 
5     * @param a the first integer
6     * @param b the second integer
7     * @return the count of common factors between a and b
8     */
9    public int commonFactors(int a, int b) {
10        // Find the greatest common divisor of a and b
11        int greatestCommonDivisor = gcd(a, b);
12      
13        // Initialize counter for common factors
14        int commonFactorCount = 0;
15      
16        // Iterate through all potential divisors from 1 to GCD
17        // All common factors of a and b must be factors of their GCD
18        for (int divisor = 1; divisor <= greatestCommonDivisor; ++divisor) {
19            // Check if current number is a factor of the GCD
20            if (greatestCommonDivisor % divisor == 0) {
21                ++commonFactorCount;
22            }
23        }
24      
25        return commonFactorCount;
26    }
27  
28    /**
29     * Calculates the greatest common divisor using Euclidean algorithm.
30     * 
31     * @param a the first integer
32     * @param b the second integer
33     * @return the greatest common divisor of a and b
34     */
35    private int gcd(int a, int b) {
36        // Base case: when b becomes 0, a is the GCD
37        // Recursive case: GCD(a, b) = GCD(b, a mod b)
38        return b == 0 ? a : gcd(b, a % b);
39    }
40}
41
1class Solution {
2public:
3    /**
4     * Count the number of common factors between two integers
5     * @param a: First integer
6     * @param b: Second integer
7     * @return: The count of common factors of a and b
8     */
9    int commonFactors(int a, int b) {
10        // Find the greatest common divisor of a and b
11        // Any common factor must divide the GCD
12        int gcdValue = gcd(a, b);
13      
14        // Initialize counter for common factors
15        int count = 0;
16      
17        // Iterate through all possible divisors of the GCD
18        // Every divisor of GCD is a common factor of both a and b
19        for (int divisor = 1; divisor <= gcdValue; ++divisor) {
20            // Check if current number is a divisor of GCD
21            if (gcdValue % divisor == 0) {
22                count++;
23            }
24        }
25      
26        return count;
27    }
28};
29
1/**
2 * Counts the number of common factors between two numbers
3 * @param a - First positive integer
4 * @param b - Second positive integer
5 * @returns The count of common factors between a and b
6 */
7function commonFactors(a: number, b: number): number {
8    // Find the greatest common divisor of a and b
9    const greatestCommonDivisor: number = gcd(a, b);
10  
11    // Initialize counter for common factors
12    let factorCount: number = 0;
13  
14    // Iterate through all potential factors from 1 to GCD
15    // All common factors must divide the GCD
16    for (let factor: number = 1; factor <= greatestCommonDivisor; factor++) {
17        // Check if current number is a factor of the GCD
18        if (greatestCommonDivisor % factor === 0) {
19            factorCount++;
20        }
21    }
22  
23    return factorCount;
24}
25
26/**
27 * Calculates the greatest common divisor (GCD) of two numbers using Euclidean algorithm
28 * @param a - First non-negative integer
29 * @param b - Second non-negative integer
30 * @returns The greatest common divisor of a and b
31 */
32function gcd(a: number, b: number): number {
33    // Base case: when b becomes 0, a is the GCD
34    // Recursive case: GCD(a, b) = GCD(b, a mod b)
35    return b === 0 ? a : gcd(b, a % b);
36}
37

Time and Space Complexity

The time complexity is O(min(a, b)) and the space complexity is O(1).

The algorithm first computes the GCD of a and b using the built-in gcd function, which has time complexity O(log(min(a, b))) using the Euclidean algorithm. Then it iterates through all integers from 1 to g (where g = gcd(a, b)), checking if each number divides g evenly. Since g ≤ min(a, b), this loop runs at most min(a, b) times. The overall time complexity is dominated by the loop, giving us O(min(a, b)).

The space complexity is O(1) because the algorithm only uses a constant amount of extra space to store the GCD value g and the loop variable x, regardless of the input size.

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

Common Pitfalls

1. Inefficient Factor Enumeration for Large GCD Values

The current solution iterates through all numbers from 1 to GCD, which can be inefficient when the GCD is large. For example, if a = 1000000 and b = 1000000, the GCD is also 1000000, requiring a million iterations.

Better Approach: Only iterate up to the square root of the GCD and count factors in pairs:

from math import gcd, isqrt

class Solution:
    def commonFactors(self, a: int, b: int) -> int:
        g = gcd(a, b)
        count = 0
      
        # Check factors up to sqrt(g)
        for i in range(1, isqrt(g) + 1):
            if g % i == 0:
                count += 1  # i is a factor
                if i != g // i:  # Avoid counting the square root twice
                    count += 1  # g//i is also a factor
      
        return count

This reduces time complexity from O(g) to O(√g).

2. Not Handling Edge Cases Properly

While the problem states that a and b are positive integers, developers might forget to validate this in production code or during testing.

Solution: Add input validation if needed:

def commonFactors(self, a: int, b: int) -> int:
    if a <= 0 or b <= 0:
        return 0  # or raise ValueError("Both numbers must be positive")
    # ... rest of the code

3. Memory Inefficiency with List Comprehension

Some developers might inadvertently create a list before counting:

# Inefficient - creates entire list in memory
factor_count = len([x for x in range(1, g + 1) if g % x == 0])

Better: Use generator expression with sum() as shown in the original solution, which doesn't create intermediate lists.

4. Integer Overflow in Other Languages

While Python handles large integers gracefully, implementing this in languages like C++ or Java requires careful consideration of integer overflow when calculating GCD or performing modulo operations with large numbers.

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

Is the following code DFS or BFS?

void search(Node root) {
  if (!root) return;
  visit(root);
  root.visited = true;
  for (Node node in root.adjacent) {
    if (!node.visited) {
      search(node);
    }
  }
}

Recommended Readings

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

Load More