3153. Sum of Digit Differences of All Pairs
Problem Description
You have an array nums
containing positive integers where every integer has the same number of digits.
The digit difference between two integers is calculated by comparing the digits at each position and counting how many positions have different digits.
For example, if we have two numbers 123
and 125
:
- Position 1 (hundreds): both have
1
→ same - Position 2 (tens): both have
2
→ same - Position 3 (ones):
3
vs5
→ different - The digit difference is
1
Your task is to find the sum of digit differences for all possible pairs of integers in the array.
For instance, with nums = [123, 125, 143]
:
- Pair (123, 125): digit difference = 1
- Pair (123, 143): digit difference = 2
- Pair (125, 143): digit difference = 2
- Total sum = 1 + 2 + 2 = 5
The solution works by processing each digit position separately. For each position, it counts how many times each digit (0-9) appears at that position across all numbers. If a digit d
appears v
times at a position, then it differs from the other n - v
numbers at that position. The formula v × (n - v)
gives the total differences involving digit d
. Summing this for all digits and dividing by 2 (since each pair is counted twice) gives the contribution of that position to the total answer.
Intuition
Instead of comparing every pair of numbers digit by digit (which would be inefficient), we can think about the problem from a different angle: process each digit position independently.
Consider what happens at a single digit position across all numbers. If we look at the rightmost digit position and see that digit 3
appears 4 times and digit 7
appears 2 times out of 6 total numbers, then:
- The 4 numbers with digit
3
will each differ from the 2 numbers with digit7
at this position - This contributes
4 × 2 = 8
to our total count
The key insight is that for any digit d
appearing v
times at a position, it contributes to the difference count with all the other n - v
numbers that have a different digit at that position. So the contribution is v × (n - v)
.
By counting the frequency of each digit (0-9) at each position and applying this formula, we avoid redundant pair-by-pair comparisons. We sum up contributions from all digits at each position, then move to the next position.
Why divide by 2? When we calculate v × (n - v)
for each digit, we're counting each pair twice. For example, if digit 3
appears 4 times and digit 7
appears 2 times, the formula counts both "3 differs from 7" and "7 differs from 3". So we divide the final sum by 2 to get the actual number of differing pairs.
The approach elegantly transforms an O(n² × m) brute force solution into an O(n × m) solution by leveraging counting and the symmetry of pairwise comparisons.
Learn more about Math patterns.
Solution Approach
The implementation follows the counting strategy described in the reference approach. Here's how the solution works step by step:
-
Initialize variables:
- Get the length of the array
n = len(nums)
- Calculate the number of digits
m = int(log10(nums[0])) + 1
(since all numbers have the same digit count) - Initialize the answer
ans = 0
- Get the length of the array
-
Process each digit position from right to left:
- For each of the
m
digit positions, create aCounter
to track digit frequencies - For each number in the array:
- Extract the rightmost digit using
divmod(x, 10)
which returns quotient and remainder - The remainder
y
is the current digit we're examining - Update the number by removing its rightmost digit (storing the quotient back)
- Count the occurrence of digit
y
in ourCounter
- Extract the rightmost digit using
- For each of the
-
Calculate contribution for current position:
- For each unique digit value
v
in our counter with its frequency:- Apply the formula:
v × (n - v)
- This counts how many times this digit differs from all other digits at this position
- Apply the formula:
- Sum all these contributions and divide by 2 (since each pair is counted twice)
- Add this to our running total
ans
- For each unique digit value
-
Return the final answer after processing all digit positions
The key formula used is:
sum(v × (n - v) for v in cnt.values()) // 2
This efficiently counts all pairwise differences at each digit position. The division by 2 corrects for double-counting since the difference between digits a
and b
is counted both when processing a
and when processing b
.
The time complexity is O(n × m)
where n
is the array length and m
is the number of digits, which is much more efficient than the brute force O(n² × m)
approach.
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 the solution with nums = [13, 23, 12]
.
Step 1: Initialize
n = 3
(array length)m = 2
(each number has 2 digits)ans = 0
Step 2: Process the ones place (rightmost digit)
Create a counter for digit frequencies at this position:
- Number 13: Extract digit 3, update to 1
- Number 23: Extract digit 3, update to 2
- Number 12: Extract digit 2, update to 1
Counter at ones place: {3: 2, 2: 1}
Calculate contribution:
- Digit 3 appears 2 times → contributes
2 × (3 - 2) = 2 × 1 = 2
- Digit 2 appears 1 time → contributes
1 × (3 - 1) = 1 × 2 = 2
- Total for this position:
(2 + 2) / 2 = 2
ans = 0 + 2 = 2
Step 3: Process the tens place (leftmost digit)
Our numbers are now [1, 2, 1] after removing the ones digit.
Create a counter for digit frequencies:
- Number 1: Extract digit 1
- Number 2: Extract digit 2
- Number 1: Extract digit 1
Counter at tens place: {1: 2, 2: 1}
Calculate contribution:
- Digit 1 appears 2 times → contributes
2 × (3 - 2) = 2 × 1 = 2
- Digit 2 appears 1 time → contributes
1 × (3 - 1) = 1 × 2 = 2
- Total for this position:
(2 + 2) / 2 = 2
ans = 2 + 2 = 4
Verification: Let's verify by checking all pairs:
- (13, 23): digits differ at both positions → difference = 2
- (13, 12): digits differ at ones position only → difference = 1
- (23, 12): digits differ at ones position only → difference = 1
- Total = 2 + 1 + 1 = 4 ✓
The solution correctly computes the sum by processing each digit position independently and using the counting formula.
Solution Implementation
1class Solution:
2 def sumDigitDifferences(self, nums: List[int]) -> int:
3 # Get the number of integers in the input list
4 num_count = len(nums)
5
6 # Calculate the number of digits in each number (assuming all have same length)
7 # log10(x) + 1 gives the number of digits in x
8 digit_count = int(log10(nums[0])) + 1
9
10 # Initialize the total sum of digit differences
11 total_differences = 0
12
13 # Process each digit position from right to left
14 for _ in range(digit_count):
15 # Counter to track frequency of each digit (0-9) at current position
16 digit_frequency = Counter()
17
18 # Extract the rightmost digit from each number
19 for index, number in enumerate(nums):
20 # divmod(x, 10) returns (quotient, remainder)
21 # quotient becomes the new number (removing rightmost digit)
22 # remainder is the extracted rightmost digit
23 nums[index], current_digit = divmod(number, 10)
24 digit_frequency[current_digit] += 1
25
26 # Calculate pairs with different digits at this position
27 # For each digit value, count * (total - count) gives pairs where
28 # one number has this digit and the other doesn't
29 # Divide by 2 to avoid counting each pair twice
30 total_differences += sum(
31 freq * (num_count - freq) for freq in digit_frequency.values()
32 ) // 2
33
34 return total_differences
35
1class Solution {
2 public long sumDigitDifferences(int[] nums) {
3 // Get the total number of integers in the array
4 int arraySize = nums.length;
5
6 // Calculate the number of digits in each integer (assuming all have same length)
7 int digitCount = (int) Math.floor(Math.log10(nums[0])) + 1;
8
9 // Array to count frequency of each digit (0-9) at current position
10 int[] digitFrequency = new int[10];
11
12 // Variable to store the total sum of digit differences
13 long totalDifferences = 0;
14
15 // Process each digit position from right to left
16 for (int digitPosition = 0; digitPosition < digitCount; digitPosition++) {
17 // Reset frequency count for current digit position
18 Arrays.fill(digitFrequency, 0);
19
20 // Count frequency of each digit at current position
21 for (int i = 0; i < arraySize; i++) {
22 // Get the rightmost digit and increment its frequency
23 int currentDigit = nums[i] % 10;
24 digitFrequency[currentDigit]++;
25
26 // Remove the rightmost digit for next iteration
27 nums[i] /= 10;
28 }
29
30 // Calculate contribution of current position to total differences
31 // For each digit, count pairs where digits are different
32 for (int digit = 0; digit < 10; digit++) {
33 // Number of pairs where one has 'digit' and other doesn't
34 // digitFrequency[digit] * (arraySize - digitFrequency[digit])
35 totalDifferences += (long) digitFrequency[digit] * (arraySize - digitFrequency[digit]);
36 }
37 }
38
39 // Divide by 2 because each pair is counted twice
40 return totalDifferences / 2;
41 }
42}
43
1class Solution {
2public:
3 long long sumDigitDifferences(vector<int>& nums) {
4 int arraySize = nums.size();
5 // Calculate the number of digits in the first number
6 int digitCount = floor(log10(nums[0])) + 1;
7
8 // Array to count frequency of each digit (0-9) at current position
9 int digitFrequency[10];
10 long long totalDifferences = 0;
11
12 // Process each digit position from right to left
13 for (int position = 0; position < digitCount; ++position) {
14 // Reset frequency array for current digit position
15 memset(digitFrequency, 0, sizeof(digitFrequency));
16
17 // Count frequency of each digit at current position
18 for (int i = 0; i < arraySize; ++i) {
19 int currentDigit = nums[i] % 10; // Extract rightmost digit
20 ++digitFrequency[currentDigit];
21 nums[i] /= 10; // Remove the processed digit
22 }
23
24 // Calculate contribution to total differences for this position
25 // For each digit value, count pairs with different digits
26 for (int digit = 0; digit < 10; ++digit) {
27 // digitFrequency[digit] numbers have this digit
28 // (arraySize - digitFrequency[digit]) numbers have different digits
29 // Each pair contributes 1 to the difference count
30 totalDifferences += 1LL * digitFrequency[digit] * (arraySize - digitFrequency[digit]);
31 }
32 }
33
34 // Divide by 2 because each pair is counted twice
35 // (once for each number in the pair)
36 return totalDifferences / 2;
37 }
38};
39
1/**
2 * Calculates the sum of digit differences across all pairs of numbers in the array.
3 * For each pair of numbers, it computes the sum of absolute differences at each digit position.
4 *
5 * @param nums - Array of positive integers with the same number of digits
6 * @returns The total sum of digit differences for all pairs
7 */
8function sumDigitDifferences(nums: number[]): number {
9 // Get the total count of numbers in the array
10 const arrayLength: number = nums.length;
11
12 // Calculate the number of digits in each number (assuming all have same digit count)
13 const digitCount: number = Math.floor(Math.log10(nums[0])) + 1;
14
15 // Use BigInt to handle potentially large sums
16 let totalSum: bigint = BigInt(0);
17
18 // Process each digit position from right to left
19 for (let digitPosition = 0; digitPosition < digitCount; digitPosition++) {
20 // Count frequency of each digit (0-9) at current position
21 const digitFrequency: number[] = Array(10).fill(0);
22
23 // Extract digit at current position for each number
24 for (let i = 0; i < arrayLength; i++) {
25 // Get the rightmost digit
26 const currentDigit: number = nums[i] % 10;
27 digitFrequency[currentDigit]++;
28
29 // Remove the rightmost digit for next iteration
30 nums[i] = Math.floor(nums[i] / 10);
31 }
32
33 // Calculate contribution of current digit position to total sum
34 // For each digit value, multiply its frequency by count of numbers with different digits
35 for (let digit = 0; digit < 10; digit++) {
36 totalSum += BigInt(digitFrequency[digit]) * BigInt(arrayLength - digitFrequency[digit]);
37 }
38 }
39
40 // Divide by 2 since each pair is counted twice (once for each order)
41 totalSum /= BigInt(2);
42
43 // Convert back to regular number for return
44 return Number(totalSum);
45}
46
Time and Space Complexity
Time Complexity: O(n × m)
The algorithm iterates through m
digits (where m
is the number of digits in each number, calculated as int(log10(nums[0])) + 1
). For each digit position, it processes all n
numbers in the array. Within each iteration:
- The loop iterates through all
n
numbers to extract the last digit and update the counter:O(n)
- Computing the sum
sum(v * (n - v) for v in cnt.values())
iterates through at most 10 distinct digits:O(1)
Therefore, the total time complexity is O(m × n)
.
Space Complexity: O(C)
where C = 10
The space usage comes from:
- The
Counter
objectcnt
which stores at most 10 different digit values (0-9) at any given time:O(10) = O(1)
- A few scalar variables (
n
,m
,ans
, loop variables):O(1)
- The input array
nums
is modified in-place, so no additional space proportional to input size is used
Since the maximum number of distinct digits is 10 (a constant), the space complexity is O(10) = O(C)
where C
is a constant equal to 10.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Modifying the Original Array In-Place
The biggest pitfall in this solution is that it destructively modifies the input array nums
. After the function executes, all elements in nums
become 0 because we repeatedly divide each number by 10 to extract digits.
Why this is problematic:
- The caller might need the original values after calling this function
- It violates the principle of least surprise - most functions don't modify their inputs unless explicitly designed to do so
- Makes the function harder to test and debug since you can't call it twice with the same array
Solution: Create a copy of the array before processing:
def sumDigitDifferences(self, nums: List[int]) -> int:
# Create a working copy to avoid modifying the original
nums_copy = nums.copy()
num_count = len(nums)
digit_count = int(log10(nums[0])) + 1
total_differences = 0
for _ in range(digit_count):
digit_frequency = Counter()
for index, number in enumerate(nums_copy):
nums_copy[index], current_digit = divmod(number, 10)
digit_frequency[current_digit] += 1
total_differences += sum(
freq * (num_count - freq) for freq in digit_frequency.values()
) // 2
return total_differences
2. Incorrect Digit Count Calculation for Edge Cases
Using int(log10(nums[0])) + 1
can fail or give incorrect results when:
nums[0]
is 0 (causes domain error in log10)- Numbers have leading zeros after extraction (though this is less likely with positive integers)
Solution: Use a more robust method to count digits:
digit_count = len(str(nums[0]))
Or handle the zero case explicitly:
digit_count = 1 if nums[0] == 0 else int(log10(nums[0])) + 1
3. Not Handling Empty Arrays
The code assumes nums[0]
exists to calculate digit count, which crashes on empty arrays.
Solution: Add an early return for edge cases:
def sumDigitDifferences(self, nums: List[int]) -> int:
if not nums or len(nums) < 2:
return 0 # No pairs possible
# Rest of the implementation...
What's the output of running the following function using the following tree as input?
1def serialize(root):
2 res = []
3 def dfs(root):
4 if not root:
5 res.append('x')
6 return
7 res.append(root.val)
8 dfs(root.left)
9 dfs(root.right)
10 dfs(root)
11 return ' '.join(res)
12
1import java.util.StringJoiner;
2
3public static String serialize(Node root) {
4 StringJoiner res = new StringJoiner(" ");
5 serializeDFS(root, res);
6 return res.toString();
7}
8
9private static void serializeDFS(Node root, StringJoiner result) {
10 if (root == null) {
11 result.add("x");
12 return;
13 }
14 result.add(Integer.toString(root.val));
15 serializeDFS(root.left, result);
16 serializeDFS(root.right, result);
17}
18
1function serialize(root) {
2 let res = [];
3 serialize_dfs(root, res);
4 return res.join(" ");
5}
6
7function serialize_dfs(root, res) {
8 if (!root) {
9 res.push("x");
10 return;
11 }
12 res.push(root.val);
13 serialize_dfs(root.left, res);
14 serialize_dfs(root.right, res);
15}
16
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
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
Want a Structured Path to Master System Design Too? Don’t Miss This!