Talentd
FleetCode
Make and follow sheets.Sign in

Sender With Largest Word Count solution and explanation

MediumArrayCountingHash TableString6 min read60.2% acceptanceUpdated 9 Apr 2026
Biweekly Contest 79 || A - 2283, B - 2284, C - 2285 Solution || Hindi ExplanationBinaryMagic · 22:35 · 547 viewsWatch on YouTube
3 more videos on this problem
  1. Biweekly Contest 79 || A - 2283, B - 2284, C - 2285 Solution || Hindi ExplanationBinaryMagic · 22:35 · 547 views
  2. 2284. Sender With Largest Word Count (Leetcode Medium)Programming Live with Larry · 4:56 · 361 views
  3. 2284. Sender With Largest Word Count || Leetcode bi weekly contest || C++CS warriors · 9:27 · 238 views
  4. Day 372: LeetCode Problem 2284. Sender With Largest Word Count - SwiftiOSxBank · 13:06 · 35 views

The problem

You have a chat log of n messages. You are given two string arrays messages and senders where messages[i] is a message sent by senders[i].

A message is list of words that are separated by a single space with no leading or trailing spaces. The word count of a sender is the total number of words sent by the sender. Note that a sender may send more than one message.

Return the sender with the largest word count. If there is more than one sender with the largest word count, return the one with the lexicographically largest name.

Note:

  • Uppercase letters come before lowercase letters in lexicographical order.
  • "Alice" and "alice" are distinct.

Example 1:

Input: messages = ["Hello userTwooo","Hi userThree","Wonderful day Alice","Nice day userThree"], senders = ["Alice","userTwo","userThree","Alice"]
Output: "Alice"
Explanation: Alice sends a total of 2 + 3 = 5 words.
userTwo sends a total of 2 words.
userThree sends a total of 3 words.
Since Alice has the largest word count, we return "Alice".

Example 2:

Input: messages = ["How is leetcode for everyone","Leetcode is useful for practice"], senders = ["Bob","Charlie"]
Output: "Charlie"
Explanation: Bob sends a total of 5 words.
Charlie sends a total of 5 words.
Since there is a tie for the largest word count, we return the sender with the lexicographically larger name, Charlie.

Constraints:

  • n == messages.length == senders.length
  • 1 <= n <= 104
  • 1 <= messages[i].length <= 100
  • 1 <= senders[i].length <= 10
  • messages[i] consists of uppercase and lowercase English letters and ' '.
  • All the words in messages[i] are separated by a single space.
  • messages[i] does not have leading or trailing spaces.
  • senders[i] consists of uppercase and lowercase English letters only.

Approach overview

Problem Overview: You receive two arrays: messages and senders. Each message belongs to the sender at the same index. The goal is to compute the total number of words sent by each sender and return the sender with the largest cumulative word count. If multiple senders tie, return the lexicographically largest sender name.

Approach 1: Divide and Conquer (O(n·m) time, O(k) space)

Split the messages array into smaller segments and compute word counts for each segment independently. Each subproblem counts words in its portion and aggregates totals in a hash map keyed by sender. During the merge step, combine maps by summing counts for identical senders. Word counting per message can be done by counting spaces and adding one, or by splitting the string. The final pass scans the aggregated map to find the sender with the maximum total, breaking ties using lexicographic comparison.

This approach mirrors classic divide and conquer patterns where large datasets are processed in chunks. It works well when message data is distributed or processed in parallel systems. The dominant cost is iterating through all characters of all messages, giving O(n·m) time where m is average message length, and O(k) space for storing word counts of k unique senders.

Approach 2: Dynamic Programming / Incremental Counting (O(n·m) time, O(k) space)

Process messages sequentially while maintaining a running total of words per sender. Use a hash table where the key is the sender name and the value is the cumulative word count. For each message, compute its word count and immediately update the sender’s total. While updating, track the current best sender by comparing totals and resolving ties using lexicographic order.

This incremental strategy behaves like a lightweight dynamic programming pattern: each state (sender total) builds on previous results instead of recomputing counts. Because every message is processed exactly once and each update is O(1) average time, the full algorithm runs in O(n·m). Space usage remains O(k) for storing totals of unique senders.

Recommended for interviews: The hash table counting approach (Approach 2) is what interviewers expect. It shows you recognize the problem as a frequency aggregation task using HashMap/dict. Mentioning the divide-and-conquer variation demonstrates awareness of scalable data processing, but the single-pass counting solution is the most direct and practical.

Approach 1: Approach 1: Divide and Conquer

This approach leverages the divide and conquer strategy to break down the problem into smaller, more manageable sub-problems. The basic idea is to recursively divide the problem into two or more sub-problems until they become simple enough to solve directly. The results of the sub-problems are then combined to give a solution to the original problem.

def merge_sort(arr):
    if len(arr) > 1:
        mid = len(arr) // 2
        left_half = arr[:mid]
        right_half = arr[mid:]

        merge_sort(left_half)
        merge_sort(right_half)

        i = j = k = 0

        while i < len(left_half) and j < len(right_half):
            if left_half[i] < right_half[j]:
                arr[k] = left_half[i]
                i += 1
            else:
                arr[k] = right_half[j]
                j += 1
            k += 1

        while i < len(left_half):
            arr[k] = left_half[i]
            i += 1
            k += 1

        while j < len(right_half):
            arr[k] = right_half[j]
            j += 1
            k += 1

arr = [12, 11, 13, 5, 6, 7]
merge_sort(arr)
print('Sorted array:', arr)
import java.util.Arrays;

public class MergeSort {

    private static void merge(int[] arr, int left, int mid, int right) {
        int[] leftArr = Arrays.copyOfRange(arr, left, mid + 1);
        int[] rightArr = Arrays.copyOfRange(arr, mid + 1, right + 1);
        int i = 0, j = 0, k = left;
        while (i < leftArr.length && j < rightArr.length) {
            if (leftArr[i] <= rightArr[j]) {
                arr[k++] = leftArr[i++];
            } else {
                arr[k++] = rightArr[j++];
            }
        }
        while (i < leftArr.length) {
            arr[k++] = leftArr[i++];
        }
        while (j < rightArr.length) {
            arr[k++] = rightArr[j++];
        }
    }

    private static void mergeSort(int[] arr, int left, int right) {
        if (left < right) {
            int mid = left + (right - left) / 2;
            mergeSort(arr, left, mid);
            mergeSort(arr, mid + 1, right);
            merge(arr, left, mid, right);
        }
    }

    public static void main(String[] args) {
        int[] arr = {12, 11, 13, 5, 6, 7};
        mergeSort(arr, 0, arr.length - 1);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }
}
#include <iostream>
#include <vector>

void merge(std::vector<int>& arr, int left, int mid, int right) {
    std::vector<int> leftArr(arr.begin() + left, arr.begin() + mid + 1);
    std::vector<int> rightArr(arr.begin() + mid + 1, arr.begin() + right + 1);
    int leftIndex = 0, rightIndex = 0, sortedIndex = left;
    while (leftIndex < leftArr.size() && rightIndex < rightArr.size()) {
        if (leftArr[leftIndex] <= rightArr[rightIndex]) {
            arr[sortedIndex++] = leftArr[leftIndex++];
        } else {
            arr[sortedIndex++] = rightArr[rightIndex++];
        }
    }
    while (leftIndex < leftArr.size()) {
        arr[sortedIndex++] = leftArr[leftIndex++];
    }
    while (rightIndex < rightArr.size()) {
        arr[sortedIndex++] = rightArr[rightIndex++];
    }
}

void mergeSort(std::vector<int>& arr, int left, int right) {
    if (left < right) {
        int mid = left + (right - left) / 2;
        mergeSort(arr, left, mid);
        mergeSort(arr, mid + 1, right);
        merge(arr, left, mid, right);
    }
}

int main() {
    std::vector<int> arr = {12, 11, 13, 5, 6, 7};
    mergeSort(arr, 0, arr.size() - 1);
    std::cout << "Sorted array: ";
    for (int i : arr)
        std::cout << i << " ";
    return 0;
}
function mergeSort(arr) {
    if (arr.length < 2) return arr;
    const mid = Math.floor(arr.length / 2);
    const left = mergeSort(arr.slice(0, mid));
    const right = mergeSort(arr.slice(mid));

    return merge(left, right);
}

function merge(left, right) {
    const sorted = [];
    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            sorted.push(left.shift());
        } else {
            sorted.push(right.shift());
        }
    }
    return [...sorted, ...left, ...right];
}

const arr = [12, 11, 13, 5, 6, 7];
console.log('Sorted array:', mergeSort(arr));
#include <stdio.h>

void conquer(int arr[], int left, int mid, int right) {
    int size1 = mid - left + 1;
    int size2 = right - mid;
    int leftArr[size1], rightArr[size2];
    for (int i = 0; i < size1; i++)
        leftArr[i] = arr[left + i];
    for (int j = 0; j < size2; j++)
        rightArr[j] = arr[mid + 1 + j];
    int i = 0, j = 0, k = left;
    while (i < size1 && j < size2) {
        if (leftArr[i] <= rightArr[j]) {
            arr[k++] = leftArr[i++];
        } else {
            arr[k++] = rightArr[j++];
        }
    }
    while (i < size1) {
        arr[k++] = leftArr[i++];
    }
    while (j < size2) {
        arr[k++] = rightArr[j++];
    }
}

void divide(int arr[], int left, int right) {
    if (left < right) {
        int mid = left + (right - left) / 2;
        divide(arr, left, mid);
        divide(arr, mid + 1, right);
        conquer(arr, left, mid, right);
    }
}

int main() {
    int arr[] = {12, 11, 13, 5, 6, 7};
    int arrSize = sizeof(arr) / sizeof(arr[0]);
    divide(arr, 0, arrSize - 1);
    printf("Sorted array: \n");
    for (int i = 0; i < arrSize; i++)
        printf("%d ", arr[i]);
    return 0;
}
using System;

class MergeSort {

    static void Merge(int[] arr, int left, int mid, int right) {
        int[] leftArr = new int[mid - left + 1];
        int[] rightArr = new int[right - mid];
        Array.Copy(arr, left, leftArr, 0, leftArr.Length);
        Array.Copy(arr, mid + 1, rightArr, 0, rightArr.Length);
        int i = 0, j = 0, k = left;
        while (i < leftArr.Length && j < rightArr.Length) {
            if (leftArr[i] <= rightArr[j]) {
                arr[k++] = leftArr[i++];
            } else {
                arr[k++] = rightArr[j++];
            }
        }
        while (i < leftArr.Length) {
            arr[k++] = leftArr[i++];
        }
        while (j < rightArr.Length) {
            arr[k++] = rightArr[j++];
        }
    }

    static void MergeSortRecursive(int[] arr, int left, int right) {
        if (left < right) {
            int mid = left + (right - left) / 2;
            MergeSortRecursive(arr, left, mid);
            MergeSortRecursive(arr, mid + 1, right);
            Merge(arr, left, mid, right);
        }
    }

    static void Main() {
        int[] arr = {12, 11, 13, 5, 6, 7};
        MergeSortRecursive(arr, 0, arr.Length - 1);
        Console.WriteLine("Sorted array: " + string.Join(", ", arr));
    }
}

This Python solution applies merge sort, dividing the array into two halves and recursively sorting and merging them.

Complexity

Time Complexity: O(n log n) - Achieved via recursive division and merge.
Space Complexity: O(n) - Due to memory allocated for auxiliary arrays during merging.

Try this approach in the editor

Approach 2: Approach 2: Dynamic Programming

This approach uses dynamic programming to build up a solution incrementally. Dynamic programming is especially useful in optimization problems where sub-problems overlap. By storing the results of sub-problems, we avoid redundant computations, thus optimizing the solution process.

def fib(n):
    dp = [0] * (n + 1)
    dp[1] = 1
    for i in range(2, n + 1):
        dp[i] = dp[i - 1] + dp[i - 2]
    return dp[n]

n = 9
print(f'Fibonacci of {n} is {fib(n)}')
public class FibonacciDP {

    static int fib(int n) {
        int[] dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = 1;

        for (int i = 2; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }

    public static void main(String[] args) {
        int n = 9;
        System.out.println("Fibonacci of " + n + " is " + fib(n));
    }
}
#include <iostream>
#include <vector>

int fib(int n) {
    std::vector<int> dp(n + 1, 0);
    dp[1] = 1;
    for (int i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
}

int main() {
    int n = 9;
    std::cout << "Fibonacci of " << n << " is " << fib(n) << std::endl;
    return 0;
}
function fib(n) {
    let dp = Array(n + 1).fill(0);
    dp[1] = 1;
    for (let i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
}

const n = 9;
console.log(`Fibonacci of ${n} is ${fib(n)}`);
#include <stdio.h>
#include <string.h>

int min(int x, int y) { return (x < y) ? x : y; }

int fib(int n) {
    int dp[n + 1];
    memset(dp, 0, sizeof(dp));
    dp[0] = 0; dp[1] = 1;

    for (int i = 2; i <= n; i++)
        dp[i] = dp[i - 1] + dp[i - 2];

    return dp[n];
}

int main() {
    int n = 9;
    printf("Fibonacci of %d is %d\n", n, fib(n));
    return 0;
}
using System;

class FibonacciDP {
    static int Fibonacci(int n) {
        int[] dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = 1;

        for (int i = 2; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }

    static void Main() {
        int n = 9;
        Console.WriteLine("Fibonacci of " + n + " is " + Fibonacci(n));
    }
}

The Python solution computes Fibonacci numbers using dynamic programming. The result of each calculation is added to a list, from which higher terms use previously computed values.

Complexity

Time Complexity: O(n) - Each step contributes to a linear time scale.
Space Complexity: O(n) - Space to store results of sub-problems.

Try this approach in the editor

Approach 3: Hash Table + Enumeration

We can use a hash table cnt to record the word count for each sender. Then, we traverse the hash table to find the sender with the highest word count. If there are multiple senders with the highest word count, we return the name that is lexicographically largest.

The time complexity is O(n + L), and the space complexity is O(n), where n is the number of messages and L is the total length of all messages.

function largestWordCount(messages: string[], senders: string[]): string {
    const cnt: { [key: string]: number } = {};

    for (let i = 0; i < messages.length; ++i) {
        const v = messages[i].split(' ').length;
        cnt[senders[i]] = (cnt[senders[i]] || 0) + v;
    }

    let ans = senders[0];
    for (const k in cnt) {
        if (cnt[ans] < cnt[k] || (cnt[ans] === cnt[k] && ans < k)) {
            ans = k;
        }
    }

    return ans;
}
func largestWordCount(messages []string, senders []string) string {
	cnt := make(map[string]int)
	for i, message := range messages {
		v := strings.Count(message, " ") + 1
		cnt[senders[i]] += v
	}

	ans := senders[0]
	for k, v := range cnt {
		if cnt[ans] < v || (cnt[ans] == v && ans < k) {
			ans = k
		}
	}
	return ans
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Approach 1: Divide and Conquer

Time Complexity: O(n log n) - Achieved via recursive division and merge.
Space Complexity: O(n) - Due to memory allocated for auxiliary arrays during merging.

Approach 2: Dynamic Programming

Time Complexity: O(n) - Each step contributes to a linear time scale.
Space Complexity: O(n) - Space to store results of sub-problems.

Hash Table + Enumeration–

Complexity analysis

ApproachTimeSpaceWhen to Use
Divide and Conquer AggregationO(n·m)O(k)Useful when processing large message datasets in parallel or distributed systems
Hash Table Incremental Counting (Dynamic Programming)O(n·m)O(k)Best general solution; single pass with constant-time updates

Frequently asked questions

Is Sender With Largest Word Count easy or hard?

The problem is typically classified as Medium because it combines string processing, counting logic, and tie-breaking rules. The algorithm itself is straightforward, but handling word counting and lexicographic comparison correctly is where mistakes often happen.

Sender With Largest Word Count Python/Java solution

In Python, use a dictionary to map sender names to word totals and compute word counts using split() or space counting. In Java, use HashMap<String, Integer> and update counts with getOrDefault. Both implementations run in O(n·m) time and O(k) space.

How to solve Sender With Largest Word Count in O(n)?

Treat each message as one processing step and maintain a hash map of sender → total word count. Count the words in the current message, add them to the sender’s total, and update the current best sender if needed. Because each message is processed once, the algorithm is linear in the number of messages, with extra cost proportional to message length.

What is the best approach for Sender With Largest Word Count?

The most efficient approach uses a hash table to accumulate word counts per sender. Iterate through the messages once, count the words in each message, and update the sender's total. Track the maximum count and resolve ties using lexicographic comparison. This solution runs in O(n·m) time and O(k) space where k is the number of unique senders.

Is Sender With Largest Word Count asked at Google/Amazon/Meta?

Problems involving frequency counting with hash maps are common in interviews at companies like Amazon, Google, and Meta. Variants often involve aggregating metrics by key and applying tie-breaking rules. This problem tests string processing, hash table usage, and careful comparison logic.

What data structure is used in Sender With Largest Word Count?

A hash table (HashMap in Java, unordered_map in C++, dict in Python) stores the cumulative word count for each sender. This allows constant-time updates and efficient lookup when aggregating totals.

What is the time complexity of Sender With Largest Word Count?

The time complexity is O(n·m), where n is the number of messages and m is the average length of a message. Each message must be scanned to count its words. Hash table updates and comparisons occur in constant average time.

Comments

Now write it yourselfClose this page and solve Sender With Largest Word Count in the editor, without looking.
Practise Sender With Largest Word Count