Four Divisors
MedPrompt
Given an integer array nums, return the sum of divisors of the integers in that array that have exactly four divisors. If there is no such integer in the array, return 0.
Example 1:
Input: nums = [21,4,7]
Output: 32
Explanation:
21 has 4 divisors: 1, 3, 7, 21
4 has 3 divisors: 1, 2, 4
7 has 2 divisors: 1, 7
The answer is the sum of divisors of 21 only.Example 2:
Input: nums = [21,21]
Output: 64Example 3:
Input: nums = [1,2,3,4,5]
Output: 0
Constraints:
1 <= nums.length <= 1041 <= nums[i] <= 105
Approaches
3 approaches with complexity analysis and trade-offs.
This is the most straightforward approach. For each number in the input array, we iterate from 1 up to the number itself to find all its divisors. We count them and sum them up. If the count is exactly four, we add this sum to our total result.
Algorithm
- Initialize a variable
totalSumto 0. - Iterate through each number
numin the input arraynums. - For each
num, initializedivisorCount = 0andcurrentSum = 0. - Start a loop with a counter
ifrom 1 tonum. - Inside the loop, check if
iis a divisor ofnum(i.e.,num % i == 0). - If it is, increment
divisorCountand additocurrentSum. - After the inner loop finishes, check if
divisorCountis equal to 4. - If it is, add
currentSumtototalSum. - After iterating through all numbers in
nums, returntotalSum.
Walkthrough
This is the most intuitive but least efficient solution. The idea is to directly translate the problem statement into code. For every number in the input array, we check every possible divisor from 1 up to the number itself.
The algorithm works as follows:
- Initialize a variable
totalSumto 0. - Loop through each number
numin the input arraynums. - For each
num, we need to find its properties. So, we initialize two temporary variables:divisorCount = 0andcurrentSum = 0. - We start another loop with a counter
ifrom 1 up tonum. - Inside this inner loop, we check if
iis a divisor ofnumusing the modulo operator (num % i == 0). - If
iis a divisor, we incrementdivisorCountand add the value ofitocurrentSum. - Once the inner loop completes (we have checked all numbers from 1 to
num), we examine thedivisorCount. - If
divisorCountis exactly 4, it meansnummeets the condition. We then add itscurrentSumto thetotalSum. - After the outer loop finishes processing all numbers in
nums, thetotalSumwill hold the final answer, which we return.
This method is simple to conceptualize but its performance is poor for large inputs.
class Solution { public int sumFourDivisors(int[] nums) { int totalSum = 0; for (int num : nums) { int divisorCount = 0; int currentSum = 0; // Iterate from 1 to num to find all divisors for (int i = 1; i <= num; i++) { if (num % i == 0) { divisorCount++; currentSum += i; } } // Check if the count of divisors is exactly 4 if (divisorCount == 4) { totalSum += currentSum; } } return totalSum; }}Complexity
Time
O(N * M), where `N` is the length of `nums` and `M` is the maximum value in `nums`. For each of the `N` numbers, we iterate up to `M`. This is too slow given the constraints (`10^4 * 10^5 = 10^9`) and will result in a Time Limit Exceeded error.
Space
O(1), as we only use a few variables to store the sums and counts.
Trade-offs
Pros
Simple to understand and implement.
Cons
Extremely inefficient and will not pass the time limits for the given constraints.
This approach improves upon the brute-force method by optimizing how we find divisors. Instead of iterating up to the number num, we only need to iterate up to its square root. If i is a divisor, then num / i is also a divisor. This significantly reduces the number of checks needed for each number.
Algorithm
- Initialize
totalSumto 0. - Iterate through each number
numinnums. - For each
num, initializedivisorCount = 0andcurrentSum = 0. - Iterate
ifrom 1 up tosqrt(num). - If
idividesnum:- If
i * i == num, we found one divisori. IncrementdivisorCountby 1 and additocurrentSum. - If
i * i != num, we found two divisors,iandnum / i. IncrementdivisorCountby 2 and addi + num / itocurrentSum.
- If
- After the loop, if
divisorCountis 4, addcurrentSumtototalSum. - Return
totalSum.
Walkthrough
The core idea is to reduce the search space for divisors. For any integer num, if i is a divisor, then num / i is also a divisor. We only need to iterate from 1 up to the integer part of sqrt(num).
The algorithm proceeds as follows:
- Initialize a variable
totalSumto 0, which will store the final result. - Iterate through each number
numin the input arraynums. - For each
num, we need to find its divisors, count them, and calculate their sum. We initializedivisorCount = 0andcurrentSum = 0. - We loop with a counter
ifrom 1 up tosqrt(num). - In each iteration, we check if
idividesnumevenly (num % i == 0).- If it does, we have found at least one divisor.
- We must handle the case where
numis a perfect square. Ifi * i == num, theniandnum / iare the same. We count this as one divisor and additocurrentSum. - Otherwise (
i * i != num), we have found two distinct divisors:iandnum / i. We count these as two divisors and add bothiandnum / itocurrentSum.
- After the loop finishes for a given
num, we check ifdivisorCountis exactly 4. - If it is, we add the
currentSumfor thisnumto ourtotalSum. - After processing all numbers in
nums,totalSumholds the required result.
Here is the implementation in Java:
class Solution { public int sumFourDivisors(int[] nums) { int totalSum = 0; for (int num : nums) { int count = 0; int currentSum = 0; // Iterate up to the square root of num for (int i = 1; i * i <= num; i++) { if (num % i == 0) { // i is a divisor if (i * i == num) { // Perfect square case, one divisor count++; currentSum += i; } else { // Two distinct divisors: i and num/i count += 2; currentSum += i + (num / i); } } } // If the number has exactly four divisors, add their sum to the total if (count == 4) { totalSum += currentSum; } } return totalSum; }}Complexity
Time
O(N * sqrt(M)), where `N` is the length of `nums` and `M` is the maximum value in `nums`. For each of the `N` numbers, we iterate up to `sqrt(M)`. With `N=10^4` and `M=10^5`, this is roughly `10^4 * 316`, which is acceptable.
Space
O(1), as we only use a few variables per number.
Trade-offs
Pros
Significantly faster than the naive brute-force approach.
Easy to implement and requires no extra space.
Cons
Can be slower than pre-computation methods if
Nis very large or if the same numbers are processed repeatedly.
Since the maximum value of a number in the array is limited (10^5), we can pre-compute the number of divisors and the sum of divisors for all integers up to this limit. This is done using a sieve-like algorithm. After the one-time pre-computation, we can answer the query for each number in the input array in constant time.
Algorithm
- Find the maximum value
max_valin thenumsarray. - Create two arrays,
divisorCountanddivisorSum, of sizemax_val + 1. - Populate these arrays using a sieve method:
- Iterate
ifrom 1 tomax_val. - For each
i, iterate through its multiplesj = i, 2*i, 3*i, ...up tomax_val. - For each multiple
j,iis a divisor. So, incrementdivisorCount[j]and additodivisorSum[j].
- Iterate
- Initialize
totalSumto 0. - Iterate through each
numin the input arraynums. - Look up
divisorCount[num]. If it is 4, adddivisorSum[num]tototalSum. - Return
totalSum.
Walkthrough
This approach leverages pre-computation to solve the problem efficiently, especially when the range of numbers is fixed and relatively small. The constraint nums[i] <= 10^5 makes this a viable strategy. We can pre-calculate the number of divisors and the sum of divisors for every number up to the maximum possible value in the input array.
The algorithm is as follows:
- First, determine the maximum value
maxValpresent in thenumsarray. This sets the upper bound for our pre-computation. - Create two integer arrays,
divisorCountanddivisorSum, both of sizemaxVal + 1.divisorCount[k]will store the number of divisors ofk, anddivisorSum[k]will store the sum of divisors ofk. - Populate these arrays using a method similar to the Sieve of Eratosthenes.
- Iterate with a variable
ifrom 1 tomaxVal. Thisirepresents a potential divisor. - For each
i, iterate through its multiplesj(i.e.,j = i, 2*i, 3*i, ...) up tomaxVal. - For each multiple
j, we know thatiis a divisor. So, we incrementdivisorCount[j]and additodivisorSum[j].
- Iterate with a variable
- After the pre-computation is complete, initialize
totalSum = 0. - Iterate through each
numin the input arraynums. - For each
num, we can now perform anO(1)lookup. IfdivisorCount[num]is equal to 4, it meansnumhas exactly four divisors. In this case, we add the pre-computeddivisorSum[num]to ourtotalSum. - Finally, return the
totalSum.
Here is the Java implementation:
class Solution { public int sumFourDivisors(int[] nums) { int maxVal = 0; for (int num : nums) { maxVal = Math.max(maxVal, num); } int[] divisorCount = new int[maxVal + 1]; int[] divisorSum = new int[maxVal + 1]; // Sieve to pre-compute divisor counts and sums for (int i = 1; i <= maxVal; i++) { for (int j = i; j <= maxVal; j += i) { divisorCount[j]++; divisorSum[j] += i; } } int totalSum = 0; // Process the input array using pre-computed values for (int num : nums) { if (num <= maxVal && divisorCount[num] == 4) { totalSum += divisorSum[num]; } } return totalSum; }}Complexity
Time
O(M * log(M) + N), where `M` is the maximum value in `nums` and `N` is the length of `nums`. The pre-computation step takes `O(M * log(M))` time. The final loop to sum up the results takes `O(N)`. This is the most efficient approach for the given constraints.
Space
O(M) to store the `divisorCount` and `divisorSum` arrays, where `M` is the maximum value in `nums`.
Trade-offs
Pros
Very fast due to pre-computation.
Each query after the initial setup is O(1).
Cons
Requires extra space proportional to the maximum value in the input array.
Solutions
Solution
class Solution { public int sumFourDivisors ( int [] nums ) { int ans = 0 ; for ( int x : nums ) { ans += f ( x ); } return ans ; } private int f ( int x ) { int cnt = 2 , s = x + 1 ; for ( int i = 2 ; i <= x / i ; ++ i ) { if ( x % i == 0 ) { ++ cnt ; s += i ; if ( i * i != x ) { ++ cnt ; s += x / i ; } } } return cnt == 4 ? s : 0 ; } }class Solution { public: int sumFourDivisors ( vector < int >& nums ) { int ans = 0 ; for ( int x : nums ) { ans += f ( x ); } return ans ; } int f ( int x ) { int cnt = 2 , s = x + 1 ; for ( int i = 2 ; i <= x / i ; ++ i ) { if ( x % i == 0 ) { ++ cnt ; s += i ; if ( i * i != x ) { ++ cnt ; s += x / i ; } } } return cnt == 4 ? s : 0 ; } };class Solution : def sumFourDivisors ( self , nums : List [ int ]) -> int : def f ( x : int ) -> int : i = 2 cnt , s = 2 , x + 1 while i <= x // i : if x % i == 0 : cnt += 1 s += i if i * i != x : cnt += 1 s += x // i i += 1 return s if cnt == 4 else 0 return sum ( f ( x ) for x in nums )Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.