3712. Sum of Elements With Frequency Divisible by K
Problem Description
You are given an integer array nums and an integer k.
Your task is to return the sum of all elements in nums whose frequency (the number of times they appear in the array) is divisible by k. If no such elements exist, return 0.
Important detail: When an element qualifies (i.e., its total frequency is divisible by k), it contributes to the sum exactly as many times as it appears in the array — not just once.
For example, if nums = [1, 2, 2, 3, 3, 3] and k = 2:
- The number
1appears1time —1 % 2 != 0, so it is excluded. - The number
2appears2times —2 % 2 == 0, so it contributes2 + 2 = 4. - The number
3appears3times —3 % 2 != 0, so it is excluded.
The answer would be 4.
In short, the problem breaks down into three steps:
- Count how many times each number appears in
nums. - Check which numbers have a frequency divisible by
k. - Sum up those numbers, multiplied by their frequencies (i.e.,
x * cnt[x]for each qualifying numberx).
How We Pick the Algorithm
Why Hash Table / Counting?
This problem maps to Hash Table / Counting through a short path in the full flowchart.
The deciding value is each number's frequency, so we count occurrences in a hash table before summing the qualifying values.
Open in FlowchartIntuition
The problem revolves entirely around one piece of information: how many times each number appears in the array. Without knowing the frequency of a number, we cannot decide whether it should be included in the sum. So the natural first thought is — count everything first, then decide.
This immediately points to using a hash table (or Counter in Python), which is the standard tool for frequency counting. One pass through nums gives us a complete mapping from each distinct number x to its frequency cnt[x].
Once the counts are available, the decision for each number becomes a simple check: is cnt[x] % k == 0?
The other key observation comes from the note in the problem: a qualifying element is counted as many times as it appears, not just once. Rather than adding x repeatedly cnt[x] times, we can capture all of its occurrences in a single multiplication — x * cnt[x]. This turns the final step into a clean aggregation:
- For each distinct number
xwith frequencyv, ifv % k == 0, addx * vto the answer.
So the approach falls out naturally from two ideas:
- Frequency is the deciding factor → count occurrences with a hash table.
- Each occurrence contributes to the sum → multiply the value by its frequency instead of summing duplicates one by one.
This gives a straightforward solution that runs in O(n) time with O(n) extra space, where n is the length of nums — a single pass to count, and a single pass over the distinct values to sum.
Solution Approach
Pattern used: Counting with a hash table.
The implementation follows two simple phases — count, then aggregate.
Step 1: Count the frequency of each number
We use a hash table cnt to record how many times each number appears:
cnt = Counter(nums)
Counter(nums) traverses the array once. For each number x, it increments cnt[x] by 1. After this pass, cnt maps every distinct value in nums to its total frequency. This is equivalent to writing:
cnt = {} for x in nums: cnt[x] = cnt.get(x, 0) + 1
Step 2: Sum the qualifying elements
Next, we traverse the hash table. For each entry (x, v) — where x is the number and v is its frequency — we check whether v is divisible by k:
- If
v % k == 0, the number qualifies. Since it must be counted once per occurrence, it contributesx * vto the total. - Otherwise, it contributes nothing.
This is expressed compactly with a generator expression:
return sum(x * v for x, v in cnt.items() if v % k == 0)
If no element satisfies the condition, the generator yields nothing and sum returns 0, which matches the required default — no special-case handling is needed.
Full Code
class Solution:
def sumDivisibleByK(self, nums: List[int], k: int) -> int:
cnt = Counter(nums)
return sum(x * v for x, v in cnt.items() if v % k == 0)
Walkthrough Example
Take nums = [1, 2, 2, 3, 3, 3, 3] and k = 2:
- Counting gives
cnt = {1: 1, 2: 2, 3: 4}. - Checking each entry:
1has frequency1→1 % 2 != 0→ skipped.2has frequency2→2 % 2 == 0→ contributes2 * 2 = 4.3has frequency4→4 % 2 == 0→ contributes3 * 4 = 12.
- Final answer:
4 + 12 = 16.
Complexity Analysis
- Time complexity:
O(n), wherenis the length ofnums. One pass to build the counter and one pass over at mostndistinct keys. - Space complexity:
O(n)in the worst case, when all elements innumsare distinct and the hash table storesnentries.
Alternative Perspective
A sorting-based approach is also possible: sort the array, scan groups of equal values, and add each group's total x * groupSize when groupSize % k == 0. This reduces extra space to O(1) (ignoring sort space) but raises time to O(n log n), making the hash table approach the better default choice.
Example Walkthrough
Let's trace the solution with nums = [3, 3, 1, 1, 1, 1, 5] and k = 2.
Step 1: Build the frequency table
Counter(nums) scans the array once, updating counts element by element:
| Element read | cnt after update |
|---|---|
3 | {3: 1} |
3 | {3: 2} |
1 | {3: 2, 1: 1} |
1 | {3: 2, 1: 2} |
1 | {3: 2, 1: 3} |
1 | {3: 2, 1: 4} |
5 | {3: 2, 1: 4, 5: 1} |
Final table: cnt = {3: 2, 1: 4, 5: 1}.
Step 2: Aggregate the qualifying entries
Now iterate over each (x, v) pair and test v % k == 0:
x | v (frequency) | v % 2 | Qualifies? | Contribution x * v | Running sum |
|---|---|---|---|---|---|
3 | 2 | 0 | ✅ Yes | 3 * 2 = 6 | 6 |
1 | 4 | 0 | ✅ Yes | 1 * 4 = 4 | 10 |
5 | 1 | 1 | ❌ No | — | 10 |
Result: 10
Notice two key behaviors confirmed by this trace:
- The element
3appears twice and contributes both occurrences (6, not3) — the multiplicationx * vhandles repetition without looping over duplicates. - The element
5is filtered out entirely because its frequency1is not divisible by2.
As a sanity check for the edge case: if we ran the same array with k = 5, no frequency (2, 4, or 1) is divisible by 5, the generator expression yields nothing, and sum naturally returns 0 — exactly the required default, with no extra code.
Solution Implementation
1class Solution:
2 def sumDivisibleByK(self, nums: List[int], k: int) -> int:
3 # Count the occurrences of each number in nums
4 counter = Counter(nums)
5 # Sum up numbers whose occurrence count is divisible by k,
6 # multiplying each number by its occurrence count
7 return sum(num * count for num, count in counter.items() if count % k == 0)
8```
9
10**Explanation:**
11
121. **Counting occurrences:** `Counter(nums)` builds a hash map where each key is a number from `nums` and each value is how many times it appears.
13
142. **Filtering and summing:** The generator expression iterates over each `(num, count)` pair:
15 - The condition `count % k == 0` keeps only numbers whose occurrence count is divisible by `k`.
16 - For each qualifying number, `num * count` adds up **all** its occurrences (not just the number once).
17
183. **Complexity:**
19 - Time: `O(n)` — one pass to count, one pass over distinct elements.
20 - Space: `O(n)` — for the counter in the worst case (all elements distinct).
21
22**Alternative perspective:** If you prefer avoiding `Counter`, a plain dictionary works equally well:
23
24```python3
25class Solution:
26 def sumDivisibleByK(self, nums: List[int], k: int) -> int:
27 # Manually count occurrences with a dictionary
28 counter = {}
29 for num in nums:
30 counter[num] = counter.get(num, 0) + 1
31 # Accumulate the total for numbers whose count is divisible by k
32 total = 0
33 for num, count in counter.items():
34 if count % k == 0:
35 total += num * count
36 return total
371class Solution {
2 public int sumDivisibleByK(int[] nums, int k) {
3 // Map to store the frequency of each number in the array
4 Map<Integer, Integer> frequencyMap = new HashMap<>();
5
6 // Count occurrences of each number
7 for (int num : nums) {
8 frequencyMap.merge(num, 1, Integer::sum);
9 }
10
11 int answer = 0;
12
13 // Iterate over each unique number and its frequency
14 for (Map.Entry<Integer, Integer> entry : frequencyMap.entrySet()) {
15 int number = entry.getKey();
16 int frequency = entry.getValue();
17
18 // If the frequency is divisible by k, add the total contribution
19 // of this number (number * frequency) to the answer
20 if (frequency % k == 0) {
21 answer += number * frequency;
22 }
23 }
24
25 return answer;
26 }
27}
281class Solution {
2public:
3 int sumDivisibleByK(vector<int>& nums, int k) {
4 // Map to store the frequency of each number in nums
5 unordered_map<int, int> countMap;
6
7 // Count the occurrences of each number
8 for (int num : nums) {
9 ++countMap[num];
10 }
11
12 int answer = 0;
13
14 // Iterate over each unique number and its frequency
15 for (auto& [num, frequency] : countMap) {
16 // If the frequency is divisible by k,
17 // add the total contribution (num * frequency) to the answer
18 if (frequency % k == 0) {
19 answer += num * frequency;
20 }
21 }
22
23 return answer;
24 }
25};
261/**
2 * Calculates the sum of all elements whose occurrence count
3 * is divisible by k.
4 *
5 * @param nums - The input array of numbers
6 * @param k - The divisor used to check occurrence counts
7 * @returns The total sum of qualifying elements (value * count)
8 */
9function sumDivisibleByK(nums: number[], k: number): number {
10 // Map to store the frequency of each number in the array
11 const countMap: Map<number, number> = new Map<number, number>();
12
13 // Count the occurrences of each number
14 for (const num of nums) {
15 countMap.set(num, (countMap.get(num) ?? 0) + 1);
16 }
17
18 // Accumulator for the final result
19 let answer: number = 0;
20
21 // Iterate over each unique number and its frequency
22 for (const [num, count] of countMap.entries()) {
23 // If the frequency is divisible by k, add the total contribution
24 if (count % k === 0) {
25 answer += num * count;
26 }
27 }
28
29 return answer;
30}
31Time and Space Complexity
-
Time Complexity:
O(n), wherenis the length of the arraynums. Building the counter withCounter(nums)requires a single pass over allnelements, and the subsequent summation iterates over at mostndistinct keys. -
Space Complexity:
O(m), wheremis the number of distinct elements in the arraynums. TheCounterstores one entry per distinct element, so the extra space grows with the number of unique values rather than the total length of the array.
Pattern Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Adding each qualifying number only once instead of once per occurrence
The most frequent mistake is summing num instead of num * count. The problem explicitly requires that a qualifying element contributes as many times as it appears in the array.
Incorrect code:
class Solution:
def sumDivisibleByK(self, nums: List[int], k: int) -> int:
counter = Counter(nums)
# WRONG: adds each qualifying number just once
return sum(num for num, count in counter.items() if count % k == 0)
Why it fails: For nums = [1, 2, 2, 3, 3, 3] and k = 2, the number 2 appears twice, so it should contribute 2 + 2 = 4. The incorrect code returns 2 instead.
Fix: Multiply each qualifying number by its frequency:
return sum(num * count for num, count in counter.items() if count % k == 0)
Pitfall 2: Checking divisibility in the wrong direction
It is easy to accidentally write k % count == 0 instead of count % k == 0. The condition must verify that the frequency is divisible by k, not the other way around.
Incorrect code:
if k % count == 0: # WRONG: tests whether k is divisible by the frequency total += num * count
Why it fails: For nums = [5, 5, 5, 5] and k = 2, the frequency of 5 is 4. The correct check 4 % 2 == 0 passes, but the reversed check 2 % 4 == 0 fails, producing 0 instead of 20. Worse, if some element's frequency happens to divide k (e.g., frequency 1), the reversed check wrongly includes it.
Fix: Always test count % k == 0.
Pitfall 3: Filtering while iterating over the raw array instead of the counter
Some implementations try to do everything in a single pass over nums, checking the running count as they go. The running count is not the final frequency, so the decision is made with incomplete information.
Incorrect code:
class Solution:
def sumDivisibleByK(self, nums: List[int], k: int) -> int:
counter = {}
total = 0
for num in nums:
counter[num] = counter.get(num, 0) + 1
# WRONG: the count here is partial, not the final frequency
if counter[num] % k == 0:
total += num
return total
Why it fails: For nums = [3, 3, 3] and k = 2, the running count of 3 hits 2 midway, so 3 is added — but its final frequency is 3, which is not divisible by 2. The correct answer is 0, yet this code returns 3.
Fix: Complete the counting phase first, then make decisions based on the final frequencies:
counter = Counter(nums)
return sum(num * count for num, count in counter.items() if count % k == 0)
A correct single-pass-over-nums variant does exist — iterate over nums a second time and add num whenever counter[num] % k == 0 — but counting must still be fully finished before any element is judged.
Pitfall 4: Assuming k could relate to the element values rather than frequencies
A careless reading may lead to filtering by num % k == 0 (the value divisible by k) instead of the frequency being divisible by k. Re-read the problem: divisibility applies to how many times the element appears, never to the element itself. Negative values in nums are perfectly fine and require no special handling, since only frequencies (always positive) interact with k.
Ready to land your dream job?
Unlock your dream job with a 5-minute quiz for a personalized study roadmap!
Get My RoadmapWhich of these pictures shows the visit order of a depth-first search?

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 If you prefer videos here's a video that explains recursion in a fun and easy way 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 him
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 describes how the time needed
Want a Structured Path to Master System Design Too? Don’t Miss This!