Taro Logo

The kth Factor of n

Medium
Asked by:
Profile picture
Profile picture
Profile picture
Profile picture
+4
12 views
Topics:
Arrays

You are given two positive integers n and k. A factor of an integer n is defined as an integer i where n % i == 0.

Consider a list of all factors of n sorted in ascending order, return the kth factor in this list or return -1 if n has less than k factors.

Example 1:

Input: n = 12, k = 3
Output: 3
Explanation: Factors list is [1, 2, 3, 4, 6, 12], the 3rd factor is 3.

Example 2:

Input: n = 7, k = 2
Output: 7
Explanation: Factors list is [1, 7], the 2nd factor is 7.

Example 3:

Input: n = 4, k = 4
Output: -1
Explanation: Factors list is [1, 2, 4], there is only 3 factors. We should return -1.

Constraints:

  • 1 <= k <= n <= 1000

Follow up:

Could you solve this problem in less than O(n) complexity?

Solution


Clarifying Questions

When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:

  1. What are the possible ranges for `n` and `k`? Could `n` or `k` be zero or negative?
  2. If `n` has less than `k` factors, what value should I return?
  3. Is `k` guaranteed to be a positive integer?
  4. By 'kth factor', do you mean the kth factor in ascending order, starting from 1?
  5. Are we concerned about integer overflow if `n` is very large?

Brute Force Solution

Approach

To find the kth factor of a number, we can simply check every number smaller than the original number to see if it divides evenly. We count how many factors we find, and stop when we reach the kth factor.

Here's how the algorithm would work step-by-step:

  1. Start with the number 1.
  2. Check if this number divides the original number evenly (meaning there's no remainder).
  3. If it does, it's a factor; count it.
  4. If the number we counted is the kth factor we're looking for, then we're done and return that number.
  5. If it's not, move on to the next number.
  6. Repeat steps 2-5 with each number, incrementing until we reach the original number.
  7. If you reach the original number without finding the kth factor, it means the original number doesn't have that many factors, so indicate that no such factor exists.

Code Implementation

def find_kth_factor(number, kth_value):
    factor_count = 0
    
    for possible_factor in range(1, number + 1):
        # Check if the possible factor divides the number evenly
        if number % possible_factor == 0:
            factor_count += 1

            # Check if we have found the kth factor
            if factor_count == kth_value:
                return possible_factor

    # If we didn't find the kth factor, return -1
    return -1

Big(O) Analysis

Time Complexity
O(n)The algorithm iterates from 1 up to n (inclusive) to find factors. In each iteration, it performs a modulo operation to check for divisibility, which takes constant time O(1). Therefore, the time complexity is directly proportional to n, the input number. Consequently, the overall time complexity is O(n).
Space Complexity
O(1)The provided solution iterates from 1 up to the input number n, checking for divisibility. It uses a counter to track the number of factors found and a variable to store the current number being checked. These variables consume constant space regardless of the size of n. No auxiliary data structures like arrays or hash maps are used to store intermediate results. Therefore, the space complexity is O(1).

Optimal Solution

Approach

To find the kth factor of a number, we want to avoid checking every single number. The trick is to realize that factors come in pairs, and we can stop checking halfway, handling both parts of the pair at once.

Here's how the algorithm would work step-by-step:

  1. Start by checking numbers from 1 up to the square root of the given number.
  2. For each number, determine if it is a factor. If it is, we've found one factor.
  3. Keep track of all the factors you find in increasing order.
  4. If you find 'k' factors before reaching the square root, you're done. Return the last factor you found.
  5. If you reach the square root and haven't found 'k' factors yet, then look at the 'other half' of the factors (the number divided by each of the factors you found earlier). Add these to your list if they haven't already been counted (to avoid duplicates when the original number is a perfect square).
  6. Now you have all the factors sorted. Return the kth factor in your sorted list.

Code Implementation

def find_kth_factor(number, kth_value):
    factors = []
    for i in range(1, int(number**0.5) + 1):
        if number % i == 0:
            factors.append(i)

            # Return if we've found enough factors
            if len(factors) == kth_value:
                return factors[-1]

    # Find the other half of factors
    factor_length = len(factors)
    for i in range(factor_length - 1, -1, -1):
        other_factor = number // factors[i]
        if other_factor != factors[i]:
            factors.append(other_factor)

            # Return if we've found enough factors
            if len(factors) == kth_value:
                return factors[-1]

    # Check if the kth factor exists
    if kth_value > len(factors):
        return -1
    else:
        # Return the kth factor
        return factors[kth_value - 1]

Big(O) Analysis

Time Complexity
O(sqrt(n))The dominant cost comes from iterating up to the square root of the input number n. Inside the loop, we perform a constant-time divisibility check. After the loop, we potentially need to iterate through the factors we've found (which will be at most sqrt(n) in number) to find the 'other half' of the factor pairs and sort them. Therefore, the time complexity is dominated by the initial loop that iterates up to the square root of n, resulting in O(sqrt(n)).
Space Complexity
O(sqrt(N))The algorithm stores factors in a list. In the worst case, up to the square root of N numbers can be factors and stored in this list before the kth factor is found or all potential factors up to the square root have been checked. Therefore, the space required for the list of factors grows proportionally to the square root of N. This means the auxiliary space complexity is O(sqrt(N)).

Edge Cases

CaseHow to Handle
n is zeroReturn -1 as zero has no factors beyond itself.
k is zero or negativeReturn -1 as factor positions are positive integers.
k is greater than the number of factors of nReturn -1 since the kth factor does not exist.
n is 1 and k is 1Return 1, as 1 is the only factor of 1.
n is a large number potentially causing integer overflow during factorizationUse long type for factor calculations or check for overflow during multiplication or division.
n is a prime numberOnly factors are 1 and n, so if k > 2, return -1.
n is a perfect square and k is the middle factor (sqrt(n))Handle the square root case carefully to avoid double counting the factor.
k is 1Return 1 since 1 is always the first factor.