Problem Statement: Given an integer N, return all divisors of N.
A divisor of an integer N is a positive integer that divides N without leaving a remainder. In other words, if N is divisible by another integer without any remainder, then that integer is considered a divisor of N.
Example:
Input: N =12
Output: [1, 2, 3, 4, 6, 12]
Explanation: The divisors of 12 are 1, 2, 3, 4, 6, 12.
Brute Force Approach:
A brute force approach would be to iterate from 1 to n checking each value if it divides n without leaving a remainder. For each divisor found, store it in an array and a count of divisors is maintained. After iterating through all possible values, the size of the array is updated with the count of divisors and the array is returned.
Algorithm:
Step 1: Initialize an array to store the divisors.
Step 2: Iterate from 1 to n using a loop variable ‘i’. For each value of ‘i’:
Check if ‘i’ is a divisor of ‘n’ by checking if ‘n’ is divisible by ‘i’ without a remainder (‘n’%i == 0).
If i is a divisor, store it in the array of divisors and increment the count of divisors.
Step 3: After the loop, return the array of divisors.
Code (Python):
Time Complexity: O(N) where N is the input number. The algorithm iterates through each number from 1 to n once to check if it is a divisor.
Space Complexity: O(N) where N is the input number. The algorithm iterates through each number from 1 to n once to check if it is a divisor.
Optimal Approach:
We can optimize the previous approach by using the property that for any non-negative integer n, if d is a divisor of n then n/d is also a divisor of n.
This property is symmetric about the square root of n by traversing just the first half we can avoid redundant iteration and computations improving the efficiency of the algorithm.
Algorithm:
Step 1: Initialize an array to store the divisors.
Step 2: Iterate from 1 to square root of n using a loop variable ‘i’. For each value of ‘i’:
Check if ‘i’ is a divisor of ‘n’ by checking if ‘n’ is divisible by ‘i’ without a remainder (‘n’%i == 0).
If i is a divisor, add it to the vectors of divisors.
If i is different from n/i add the counterpart divisor n/i to the vector of divisors.
Step 3: After the loop, return the array of divisors.
Code (Python):
Time Complexity: O(sqrt(N)) where N is the input number. The algorithm iterates through each number from 1 to the square root of N once to check if it is a divisor.
Space Complexity: O(2*sqrt(N)) where N is the input number. This approach allocates memory for an array to hold all the divisors. The size of this array could go to be 2*(sqrt(N)).
Conclusion:
Such amazing approach the second one is. Though unknowingly I knew that the concept of square roots and divisors it's hard to apply all those in one to make logic to solve other problems. This is what I found very interesting.