1492. The kth Factor of n
Problem Description
You need to find the k-th smallest factor of a positive integer n.
A factor of n is any integer i where n is divisible by i (meaning n % i == 0
). For example, the factors of 12 are: 1, 2, 3, 4, 6, and 12.
Given two positive integers:
n
: the number whose factors you need to findk
: the position of the factor you want (1st, 2nd, 3rd, etc.)
Your task is to:
- Find all factors of n
- Sort them in ascending order (smallest to largest)
- Return the k-th factor from this sorted list
If n has fewer than k factors, return -1.
Example walkthrough:
- If
n = 12
andk = 3
- The factors of 12 in ascending order are: [1, 2, 3, 4, 6, 12]
- The 3rd factor is 3
- Return 3
The solution iterates through all numbers from 1 to n, checking if each number divides n evenly. It counts each factor found and returns the k-th one when reached. If after checking all numbers from 1 to n, fewer than k factors were found, it returns -1.
Intuition
The most straightforward way to find the k-th factor is to check every possible number that could be a factor. Since a factor must divide n evenly, we need to test each number from 1 to n to see if it divides n without a remainder.
Why start from 1 and go up to n? Because:
- 1 is always a factor of any positive integer
- n itself is always a factor of n
- All other factors must lie between these two values
As we iterate through numbers from 1 to n, we can use a counter to keep track of how many factors we've found so far. Each time we find a number i
where n % i == 0
, we know it's a factor, so we decrement our counter k. When k reaches 0, we've found exactly k factors, and the current number is our answer.
The beauty of iterating from 1 upward is that we naturally encounter factors in ascending order. We don't need to store all factors in a list and then sort them - the sequential checking gives us the sorted order automatically.
If we complete the entire loop from 1 to n without k reaching 0, it means n has fewer than k factors, so we return -1.
This approach trades potential efficiency for simplicity and clarity. While we could optimize by only checking up to √n
(since factors come in pairs), the brute force method is easier to understand and implement, making it less prone to errors.
Learn more about Math patterns.
Solution Approach
The implementation uses a simple linear search algorithm to find the k-th factor:
Step-by-step implementation:
-
Iterate through potential factors: Use a for loop to check every integer from 1 to n inclusive:
for i in range(1, n + 1):
-
Check if i is a factor: For each number i, test if it divides n evenly using the modulo operator:
if n % i == 0:
When
n % i == 0
, we know that i is a factor of n. -
Count the factors: Each time we find a factor, decrement k by 1:
k -= 1
This effectively counts down from k to 0, tracking how many more factors we need to find.
-
Return when k-th factor is found: When k reaches 0, we've found exactly k factors, and the current value of i is our answer:
if k == 0: return i
-
Handle insufficient factors: If the loop completes without finding k factors (k never reached 0), return -1:
return -1
Time and Space Complexity:
- Time Complexity:
O(n)
- We iterate through all numbers from 1 to n in the worst case - Space Complexity:
O(1)
- We only use a constant amount of extra space for the loop variable and counter
The algorithm doesn't require any additional data structures like arrays or lists to store factors. By processing factors in their natural ascending order and using a countdown mechanism with k, we achieve an elegant solution that directly returns the k-th factor when found.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through finding the 4th smallest factor of n = 20.
Step 1: Initialize
- n = 20, k = 4
- We need to find the 4th factor of 20
Step 2: Iterate and check each number
-
i = 1: Is 20 % 1 == 0? Yes! (20 ÷ 1 = 20)
- Found a factor, k = 4 - 1 = 3
- k ≠ 0, continue
-
i = 2: Is 20 % 2 == 0? Yes! (20 ÷ 2 = 10)
- Found a factor, k = 3 - 1 = 2
- k ≠ 0, continue
-
i = 3: Is 20 % 3 == 0? No (20 ÷ 3 = 6 remainder 2)
- Not a factor, k stays at 2, continue
-
i = 4: Is 20 % 4 == 0? Yes! (20 ÷ 4 = 5)
- Found a factor, k = 2 - 1 = 1
- k ≠ 0, continue
-
i = 5: Is 20 % 5 == 0? Yes! (20 ÷ 5 = 4)
- Found a factor, k = 1 - 1 = 0
- k == 0, we found our 4th factor!
- Return 5
Result: The 4th smallest factor of 20 is 5.
For reference, all factors of 20 are: [1, 2, 4, 5, 10, 20], and indeed the 4th one is 5.
Solution Implementation
1class Solution:
2 def kthFactor(self, n: int, k: int) -> int:
3 """
4 Find the kth factor of n in ascending order.
5
6 Args:
7 n: The number to find factors of
8 k: The position of the factor to return (1-indexed)
9
10 Returns:
11 The kth factor of n, or -1 if n has less than k factors
12 """
13 # Iterate through all potential factors from 1 to n
14 for i in range(1, n + 1):
15 # Check if i is a factor of n
16 if n % i == 0:
17 # Decrement k for each factor found
18 k -= 1
19 # If we've found the kth factor, return it
20 if k == 0:
21 return i
22
23 # If we've checked all numbers and k > 0, n has fewer than k factors
24 return -1
25
1class Solution {
2 /**
3 * Finds the kth factor of a given number n.
4 * Factors are listed in ascending order.
5 *
6 * @param n The number to find factors of
7 * @param k The position of the factor to return (1-indexed)
8 * @return The kth factor if it exists, otherwise -1
9 */
10 public int kthFactor(int n, int k) {
11 // Iterate through all potential factors from 1 to n
12 for (int potentialFactor = 1; potentialFactor <= n; potentialFactor++) {
13 // Check if current number is a factor of n
14 if (n % potentialFactor == 0) {
15 // Decrement k and check if we've found the kth factor
16 k--;
17 if (k == 0) {
18 // Found the kth factor
19 return potentialFactor;
20 }
21 }
22 }
23
24 // If k factors don't exist, return -1
25 return -1;
26 }
27}
28
1class Solution {
2public:
3 /**
4 * Find the k-th factor of n in ascending order.
5 *
6 * @param n: The number to find factors of
7 * @param k: The position of the factor to return (1-indexed)
8 * @return: The k-th factor if it exists, otherwise -1
9 */
10 int kthFactor(int n, int k) {
11 // Iterate through all potential factors from 1 to n
12 for (int factor = 1; factor <= n; ++factor) {
13 // Check if current number is a factor of n
14 if (n % factor == 0) {
15 // Decrement k and check if we've found the k-th factor
16 --k;
17 if (k == 0) {
18 return factor;
19 }
20 }
21 }
22
23 // If k factors don't exist, return -1
24 return -1;
25 }
26};
27
1/**
2 * Finds the k-th factor of a given number n
3 * @param n - The number to find factors for
4 * @param k - The position of the factor to return (1-indexed)
5 * @returns The k-th factor of n, or -1 if n has less than k factors
6 */
7function kthFactor(n: number, k: number): number {
8 // Iterate through all potential factors from 1 to n
9 for (let i = 1; i <= n; i++) {
10 // Check if i is a factor of n
11 if (n % i === 0) {
12 // Decrement k and check if we've found the k-th factor
13 k--;
14 if (k === 0) {
15 return i;
16 }
17 }
18 }
19
20 // If we've exhausted all factors and haven't found the k-th one
21 return -1;
22}
23
Time and Space Complexity
The time complexity is O(n)
because the algorithm iterates through all integers from 1 to n in the worst case. In each iteration, it performs a constant-time modulo operation to check if i
is a factor of n
. The loop runs at most n
times, making the overall time complexity linear with respect to n
.
The space complexity is O(1)
because the algorithm only uses a fixed amount of extra space regardless of the input size. It maintains only a few variables (i
for the loop counter and the parameter k
which is decremented) that don't grow with the input size n
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Inefficient O(n) Time Complexity for Large Numbers
The current solution always iterates from 1 to n, which becomes extremely slow for large values of n. For example, if n = 1,000,000 and k = 2, the algorithm still checks all million numbers even though the answer is 2.
Better Approach: Optimize by only iterating up to √n, since factors come in pairs:
class Solution:
def kthFactor(self, n: int, k: int) -> int:
factors = []
# Find factors up to sqrt(n)
for i in range(1, int(n**0.5) + 1):
if n % i == 0:
factors.append(i)
if len(factors) == k:
return i
# Handle the second half of factors in reverse
start = len(factors) - 1
if factors[-1]**2 == n: # Perfect square case
start -= 1
for i in range(start, -1, -1):
k -= 1
if k == 0:
return n // factors[i]
return -1
2. Not Handling Edge Cases Properly
The naive implementation doesn't validate inputs, which could lead to unexpected behavior:
- What if k = 0 or k < 0?
- What if n = 0 or n < 0?
Solution: Add input validation:
def kthFactor(self, n: int, k: int) -> int:
if n <= 0 or k <= 0:
return -1
# Rest of the implementation
3. Memory Usage When Only One Factor is Needed
Some developers might instinctively collect all factors first, then return the k-th one:
# Inefficient approach - don't do this!
def kthFactor(self, n: int, k: int) -> int:
factors = []
for i in range(1, n + 1):
if n % i == 0:
factors.append(i)
return factors[k-1] if k <= len(factors) else -1
This uses O(d) space where d is the number of divisors, which is unnecessary when we only need one specific factor.
4. Integer Overflow in Other Languages
While Python handles arbitrary-precision integers automatically, implementing this in languages like C++ or Java requires careful consideration of integer overflow when dealing with large values of n.
5. Off-by-One Errors with k
Developers might confuse whether k is 0-indexed or 1-indexed. The problem specifies k is 1-indexed (k=1 means the first factor), but it's easy to make mistakes when decrementing k or accessing array indices.
How many ways can you arrange the three letters A, B and C?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!