2644. Find the Maximum Divisibility Score
Problem Description
You are given two integer arrays: nums
and divisors
.
For each element in the divisors
array, you need to calculate its divisibility score. The divisibility score of divisors[i]
is defined as the count of elements in nums
that are divisible by divisors[i]
.
Your task is to find which element in divisors
has the highest divisibility score and return that element. If there's a tie (multiple elements have the same maximum score), you should return the smallest element among them.
For example:
- If
nums = [4, 6, 8]
anddivisors = [2, 3]
- For
divisors[0] = 2
: elements 4, 6, and 8 are all divisible by 2, so score = 3 - For
divisors[1] = 3
: only element 6 is divisible by 3, so score = 1 - Since 2 has the higher score (3 > 1), we return 2
The key points are:
- Calculate how many numbers in
nums
each divisor can divide evenly (remainder is 0) - Find the divisor with the maximum count
- If multiple divisors have the same maximum count, choose the smallest divisor value
Intuition
The problem asks us to find the "best" divisor based on how many numbers it can divide. This naturally leads us to think about checking each divisor individually and counting its performance.
Since we need to know the divisibility score for every divisor to determine which one is the maximum, we can't avoid checking all of them. This means we need to iterate through each divisor and count how many numbers from nums
it can divide.
For each divisor div
, we go through all numbers in nums
and check if each number is divisible by div
using the modulo operation (num % div == 0
). If the remainder is 0, the number is divisible.
As we calculate each divisor's score, we need to keep track of:
- The maximum score seen so far (
mx
) - The divisor that achieved this maximum score (
ans
)
The comparison logic follows naturally from the problem requirements:
- When we find a divisor with a higher score than our current maximum, it becomes our new best candidate
- When we find a divisor with the same score as our maximum, we only update if this divisor is smaller (since the problem asks for the smallest divisor in case of ties)
This straightforward enumeration approach works well because we must examine every divisor anyway to ensure we find the one with the maximum score. There's no way to skip checking any divisor since any of them could potentially have the highest score.
Solution Approach
The solution uses a simple enumeration approach to find the divisor with the maximum divisibility score.
We initialize two variables:
ans = divisors[0]
: Stores the divisor with the maximum score (initially set to the first divisor)mx = 0
: Stores the current maximum divisibility score
For each divisor div
in the divisors
array, we:
-
Calculate the divisibility score: Count how many elements in
nums
are divisible bydiv
- This is done using
sum(x % div == 0 for x in nums)
- The expression
x % div == 0
returnsTrue
(counted as 1) ifx
is divisible bydiv
, otherwiseFalse
(counted as 0) - The
sum()
function adds up all theTrue
values to get the total count
- This is done using
-
Update the maximum based on the score:
- If
cnt > mx
: We found a better divisor with a higher score- Update both
mx = cnt
andans = div
- Update both
- If
cnt == mx and div < ans
: We found a divisor with the same score but smaller value- Update
ans = div
to keep the smallest divisor with the maximum score
- Update
- If
-
Return the result: After checking all divisors,
ans
contains the divisor with the maximum score (and the smallest value in case of ties)
The time complexity is O(n × m)
where n
is the length of nums
and m
is the length of divisors
, since for each divisor we check all numbers. The space complexity is O(1)
as we only use a constant amount of extra space for variables.
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 a concrete example with nums = [12, 6, 15, 9]
and divisors = [3, 6, 2]
.
We start by initializing:
ans = divisors[0] = 3
(our current best divisor)mx = 0
(the maximum score seen so far)
Step 1: Check divisor = 3
- Count elements in nums divisible by 3:
- 12 % 3 = 0 ✓ (divisible)
- 6 % 3 = 0 ✓ (divisible)
- 15 % 3 = 0 ✓ (divisible)
- 9 % 3 = 0 ✓ (divisible)
- Score = 4
- Since 4 > 0 (our current max), update:
mx = 4
,ans = 3
Step 2: Check divisor = 6
- Count elements in nums divisible by 6:
- 12 % 6 = 0 ✓ (divisible)
- 6 % 6 = 0 ✓ (divisible)
- 15 % 6 = 3 ✗ (not divisible)
- 9 % 6 = 3 ✗ (not divisible)
- Score = 2
- Since 2 < 4 (our current max), no update needed
Step 3: Check divisor = 2
- Count elements in nums divisible by 2:
- 12 % 2 = 0 ✓ (divisible)
- 6 % 2 = 0 ✓ (divisible)
- 15 % 2 = 1 ✗ (not divisible)
- 9 % 2 = 1 ✗ (not divisible)
- Score = 2
- Since 2 < 4 (our current max), no update needed
Result: Return ans = 3
as it has the highest divisibility score of 4.
Note how if divisor 2 had also scored 4, we would have updated ans = 2
since 2 < 3 (choosing the smaller divisor in case of a tie).
Solution Implementation
1from typing import List
2
3class Solution:
4 def maxDivScore(self, nums: List[int], divisors: List[int]) -> int:
5 """
6 Find the divisor that has the maximum divisibility score.
7 The divisibility score is the count of elements in nums that are divisible by the divisor.
8 If multiple divisors have the same score, return the smallest one.
9
10 Args:
11 nums: List of integers to check divisibility
12 divisors: List of candidate divisors
13
14 Returns:
15 The divisor with the maximum divisibility score
16 """
17 # Initialize with the first divisor and score of 0
18 best_divisor = divisors[0]
19 max_score = 0
20
21 # Check each divisor
22 for divisor in divisors:
23 # Count how many numbers in nums are divisible by current divisor
24 current_score = sum(num % divisor == 0 for num in nums)
25
26 # Update if we found a better score
27 if max_score < current_score:
28 max_score = current_score
29 best_divisor = divisor
30 # If same score, choose the smaller divisor
31 elif max_score == current_score and best_divisor > divisor:
32 best_divisor = divisor
33
34 return best_divisor
35
1class Solution {
2 public int maxDivScore(int[] nums, int[] divisors) {
3 // Initialize result with the first divisor
4 int result = divisors[0];
5 // Track the maximum count of divisible numbers found so far
6 int maxCount = 0;
7
8 // Iterate through each divisor to find the one with maximum divisibility score
9 for (int divisor : divisors) {
10 // Count how many numbers in nums are divisible by current divisor
11 int currentCount = 0;
12 for (int number : nums) {
13 if (number % divisor == 0) {
14 currentCount++;
15 }
16 }
17
18 // Update result if we found a better divisor (higher count)
19 if (currentCount > maxCount) {
20 maxCount = currentCount;
21 result = divisor;
22 }
23 // If count is the same, choose the smaller divisor
24 else if (currentCount == maxCount) {
25 result = Math.min(result, divisor);
26 }
27 }
28
29 return result;
30 }
31}
32
1class Solution {
2public:
3 int maxDivScore(vector<int>& nums, vector<int>& divisors) {
4 // Initialize the result with the first divisor
5 int result = divisors[0];
6 // Track the maximum count of divisible numbers found so far
7 int maxCount = 0;
8
9 // Iterate through each divisor to find the one with the highest score
10 for (int currentDivisor : divisors) {
11 // Count how many numbers in nums are divisible by the current divisor
12 int divisibleCount = 0;
13 for (int number : nums) {
14 // Increment count if the number is divisible by current divisor
15 divisibleCount += (number % currentDivisor == 0);
16 }
17
18 // Update result if we found a higher score
19 if (maxCount < divisibleCount) {
20 maxCount = divisibleCount;
21 result = currentDivisor;
22 }
23 // If score is the same, choose the smaller divisor
24 else if (maxCount == divisibleCount) {
25 result = min(result, currentDivisor);
26 }
27 }
28
29 return result;
30 }
31};
32
1/**
2 * Finds the divisor with the maximum divisibility score.
3 * The divisibility score is the count of numbers in nums that are divisible by the divisor.
4 * If multiple divisors have the same score, returns the smallest divisor.
5 *
6 * @param nums - Array of numbers to check divisibility against
7 * @param divisors - Array of potential divisors to evaluate
8 * @returns The divisor with the maximum divisibility score
9 */
10function maxDivScore(nums: number[], divisors: number[]): number {
11 // Initialize result with the first divisor
12 let result: number = divisors[0];
13
14 // Track the maximum divisibility score found so far
15 let maxScore: number = 0;
16
17 // Iterate through each divisor to calculate its divisibility score
18 for (const divisor of divisors) {
19 // Count how many numbers in nums are divisible by current divisor
20 const divisibilityCount: number = nums.reduce(
21 (accumulator: number, currentNum: number) =>
22 accumulator + (currentNum % divisor === 0 ? 1 : 0),
23 0
24 );
25
26 // Update result if we found a better score
27 if (maxScore < divisibilityCount) {
28 maxScore = divisibilityCount;
29 result = divisor;
30 }
31 // If same score, choose the smaller divisor
32 else if (maxScore === divisibilityCount && result > divisor) {
33 result = divisor;
34 }
35 }
36
37 return result;
38}
39
Time and Space Complexity
The time complexity is O(m × n)
, where m
is the length of divisors
and n
is the length of nums
. This is because the code iterates through each divisor in divisors
(outer loop with m
iterations), and for each divisor, it iterates through all elements in nums
to count how many are divisible by that divisor (inner iteration with n
elements via the sum
function with generator expression). Therefore, the total number of modulo operations performed is m × n
.
The space complexity is O(1)
. The algorithm only uses a constant amount of extra space for variables ans
, mx
, div
, and cnt
, regardless of the input size. The generator expression (x % div == 0 for x in nums)
doesn't create an intermediate list but generates values on-the-fly, so it doesn't consume additional space proportional to the input size.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Division by Zero Error
The Problem: If any element in the divisors
array is 0, the modulo operation num % divisor
will raise a ZeroDivisionError
. This is a critical runtime error that will crash the program.
Example of the issue:
nums = [4, 6, 8] divisors = [2, 0, 3] # Contains 0 # When checking divisor = 0: num % 0 raises ZeroDivisionError
Solution: Add a check to handle zero divisors safely:
def maxDivScore(self, nums: List[int], divisors: List[int]) -> int:
best_divisor = divisors[0]
max_score = 0
for divisor in divisors:
if divisor == 0:
# Handle zero divisor - skip it or treat specially
# Option 1: Skip zero divisors
continue
# Option 2: Treat 0 as having score 0
# current_score = 0
else:
current_score = sum(num % divisor == 0 for num in nums)
if max_score < current_score:
max_score = current_score
best_divisor = divisor
elif max_score == current_score and best_divisor > divisor:
best_divisor = divisor
return best_divisor
2. Incorrect Tie-Breaking Logic
The Problem: The original code has a subtle bug in the tie-breaking condition. It uses best_divisor > divisor
instead of divisor < best_divisor
. While mathematically equivalent, the condition max_score == current_score and best_divisor > divisor
can be confusing and prone to logical errors during maintenance.
More importantly, if the first divisor happens to be the answer (has the maximum score and is the smallest among ties), the initialization might cause issues if not handled properly.
Solution: Use clearer logic and ensure proper initialization:
def maxDivScore(self, nums: List[int], divisors: List[int]) -> int:
best_divisor = divisors[0]
max_score = -1 # Initialize to -1 to ensure first divisor is properly evaluated
for divisor in divisors:
current_score = sum(num % divisor == 0 for num in nums)
# Clearer tie-breaking logic
if current_score > max_score or (current_score == max_score and divisor < best_divisor):
max_score = current_score
best_divisor = divisor
return best_divisor
3. Empty Arrays Not Handled
The Problem: The code assumes both nums
and divisors
are non-empty. If divisors
is empty, divisors[0]
will raise an IndexError
.
Solution: Add validation for edge cases:
def maxDivScore(self, nums: List[int], divisors: List[int]) -> int:
if not divisors:
raise ValueError("divisors array cannot be empty")
if not nums:
# All divisors have score 0, return the smallest divisor
return min(divisors)
# Rest of the implementation...
You are given an array of intervals where intervals[i] = [start_i, end_i]
represent the start and end of the ith
interval. You need to merge all overlapping intervals and return an array of the non-overlapping intervals that cover all the intervals in the input.
Recommended Readings
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
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!