2894. Divisible and Non-divisible Sums Difference
Problem Description
You are given two positive integers n
and m
.
The problem asks you to calculate the difference between two sums:
- num1: The sum of all integers from 1 to
n
that are not divisible bym
- num2: The sum of all integers from 1 to
n
that are divisible bym
Your task is to return the value of num1 - num2
.
For example, if n = 10
and m = 3
:
- Numbers from 1 to 10 that are not divisible by 3:
1, 2, 4, 5, 7, 8, 10
- Their sum (num1) =
1 + 2 + 4 + 5 + 7 + 8 + 10 = 37
- Their sum (num1) =
- Numbers from 1 to 10 that are divisible by 3:
3, 6, 9
- Their sum (num2) =
3 + 6 + 9 = 18
- Their sum (num2) =
- The answer would be
37 - 18 = 19
The solution iterates through all numbers from 1 to n
. For each number i
, if it's divisible by m
(i.e., i % m == 0
), it subtracts the number from the running total. Otherwise, it adds the number to the running total. This effectively calculates num1 - num2
in a single pass.
Intuition
The straightforward approach would be to calculate num1
and num2
separately by iterating through the range twice or maintaining two separate sums. However, we can optimize this by recognizing a key pattern in the calculation.
When we compute num1 - num2
, we're essentially:
- Adding numbers that are not divisible by
m
- Subtracting numbers that are divisible by
m
This means for each number i
in the range [1, n]
:
- If
i
is not divisible bym
, it contributes+i
to our final answer - If
i
is divisible bym
, it contributes-i
to our final answer
Instead of maintaining two separate sums and then subtracting them, we can directly compute the final result in a single pass. For each number, we check if it's divisible by m
using the modulo operator (i % m
). If the remainder is 0 (meaning it's divisible), we subtract it; otherwise, we add it.
The clever part of the solution uses the fact that i % m
evaluates to 0 (falsy) when i
is divisible by m
, and a non-zero value (truthy) otherwise. This allows us to write a concise conditional expression: i if i % m else -i
, which adds i
when it's not divisible by m
and subtracts i
when it is divisible by m
.
This approach reduces both the code complexity and ensures we only need one iteration through the range, making the solution both elegant and efficient.
Learn more about Math patterns.
Solution Approach
The solution uses a simulation approach where we traverse every number in the range [1, n]
and apply the appropriate operation based on divisibility by m
.
Implementation Steps:
-
Iterate through the range: We loop through all integers from 1 to
n
(inclusive) usingrange(1, n + 1)
. -
Check divisibility and accumulate: For each number
i
in the range:- We check if
i
is divisible bym
using the modulo operatori % m
- If
i % m
equals 0 (number is divisible bym
), we subtract it from our running total - If
i % m
is non-zero (number is not divisible bym
), we add it to our running total
- We check if
-
Return the result: The accumulated sum directly gives us
num1 - num2
.
Code Implementation:
class Solution:
def differenceOfSums(self, n: int, m: int) -> int:
return sum(i if i % m else -i for i in range(1, n + 1))
The solution leverages Python's generator expression with a conditional operator:
i if i % m else -i
: This expression evaluates toi
wheni % m
is non-zero (truthy), meaning the number is not divisible bym
. It evaluates to-i
wheni % m
is 0 (falsy), meaning the number is divisible bym
.- The
sum()
function then accumulates all these values, effectively calculating the difference between the sum of non-divisible numbers and divisible numbers in a single pass.
Time Complexity: O(n)
- We iterate through all numbers from 1 to n once.
Space Complexity: O(1)
- We only use a constant amount of extra space for the calculation.
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 n = 5
and m = 2
:
Step 1: Identify the numbers
- Range: [1, 2, 3, 4, 5]
- Numbers divisible by 2: [2, 4]
- Numbers not divisible by 2: [1, 3, 5]
Step 2: Apply the solution logic
Our solution iterates through each number and applies the conditional: i if i % m else -i
i | i % 2 | Condition Result | Running Sum |
---|---|---|---|
1 | 1 (truthy) | +1 | 1 |
2 | 0 (falsy) | -2 | 1 + (-2) = -1 |
3 | 1 (truthy) | +3 | -1 + 3 = 2 |
4 | 0 (falsy) | -4 | 2 + (-4) = -2 |
5 | 1 (truthy) | +5 | -2 + 5 = 3 |
Step 3: Verify the result
- num1 (sum of non-divisible): 1 + 3 + 5 = 9
- num2 (sum of divisible): 2 + 4 = 6
- num1 - num2 = 9 - 6 = 3 ✓
The solution correctly returns 3 by adding non-divisible numbers and subtracting divisible numbers in a single pass through the range.
Solution Implementation
1class Solution:
2 def differenceOfSums(self, n: int, m: int) -> int:
3 """
4 Calculate the difference between the sum of integers not divisible by m
5 and the sum of integers divisible by m in the range [1, n].
6
7 Args:
8 n: The upper bound of the range (inclusive)
9 m: The divisor to check divisibility
10
11 Returns:
12 The difference: sum(not divisible by m) - sum(divisible by m)
13 """
14 # Iterate through numbers from 1 to n (inclusive)
15 # If number is not divisible by m (i % m != 0), add it to the sum
16 # If number is divisible by m (i % m == 0), subtract it from the sum
17 return sum(i if i % m != 0 else -i for i in range(1, n + 1))
18
1class Solution {
2 /**
3 * Calculate the difference between the sum of all integers from 1 to n that are NOT divisible by m
4 * and the sum of all integers from 1 to n that ARE divisible by m.
5 *
6 * @param n The upper bound of the range (inclusive)
7 * @param m The divisor to check divisibility
8 * @return The difference: sum(non-divisible) - sum(divisible)
9 */
10 public int differenceOfSums(int n, int m) {
11 int result = 0;
12
13 // Iterate through all numbers from 1 to n
14 for (int i = 1; i <= n; i++) {
15 // If i is divisible by m, subtract it from result
16 // Otherwise, add it to result
17 if (i % m == 0) {
18 result -= i; // Subtract numbers divisible by m
19 } else {
20 result += i; // Add numbers not divisible by m
21 }
22 }
23
24 return result;
25 }
26}
27
1class Solution {
2public:
3 int differenceOfSums(int n, int m) {
4 int result = 0;
5
6 // Iterate through all numbers from 1 to n
7 for (int i = 1; i <= n; ++i) {
8 // If i is not divisible by m, add it to result
9 // If i is divisible by m, subtract it from result
10 result += (i % m != 0) ? i : -i;
11 }
12
13 return result;
14 }
15};
16
1/**
2 * Calculates the difference between sum of numbers not divisible by m
3 * and sum of numbers divisible by m in range [1, n]
4 * @param n - The upper bound of the range (inclusive)
5 * @param m - The divisor to check divisibility
6 * @returns The difference between the two sums
7 */
8function differenceOfSums(n: number, m: number): number {
9 let totalDifference: number = 0;
10
11 // Iterate through all numbers from 1 to n
12 for (let currentNumber: number = 1; currentNumber <= n; ++currentNumber) {
13 // If current number is not divisible by m, add it to the sum
14 // If current number is divisible by m, subtract it from the sum
15 totalDifference += currentNumber % m !== 0 ? currentNumber : -currentNumber;
16 }
17
18 return totalDifference;
19}
20
Time and Space Complexity
The time complexity is O(n)
, where n
is the given integer. This is because the code iterates through all integers from 1 to n exactly once using the range function range(1, n + 1)
. For each integer i
in this range, it performs a constant-time operation (checking divisibility by m
and either adding or subtracting the value).
The space complexity is O(1)
. Although the code uses a generator expression (i if i % m else -i for i in range(1, n + 1))
, the sum()
function processes it iteratively without storing all values in memory at once. The generator yields one value at a time, and only a constant amount of extra space is used to maintain the running sum and loop variables.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Integer Overflow in Other Languages
While Python handles arbitrarily large integers automatically, implementing this solution in languages like C++ or Java could lead to integer overflow for large values of n
.
Problem Example:
- If
n = 10^9
, the sum of numbers from 1 to n is approximatelyn*(n+1)/2 ≈ 5*10^17
, which exceeds the range of 32-bit integers and even 64-bit integers in some cases.
Solution:
- Use appropriate data types (
long long
in C++,long
in Java) - Consider using mathematical formulas to avoid iteration when possible
2. Inefficient for Large Values of n
The O(n) time complexity means iterating through potentially billions of numbers when n is large, which can be slow.
Optimized Mathematical Approach:
class Solution:
def differenceOfSums(self, n: int, m: int) -> int:
# Calculate total sum using formula: n*(n+1)/2
total_sum = n * (n + 1) // 2
# Calculate sum of multiples of m
# Numbers divisible by m: m, 2m, 3m, ..., km where k = n//m
k = n // m
sum_divisible = m * k * (k + 1) // 2
# num1 = total_sum - sum_divisible (sum of non-divisible)
# num2 = sum_divisible (sum of divisible)
# Result = num1 - num2 = (total_sum - sum_divisible) - sum_divisible
return total_sum - 2 * sum_divisible
This reduces time complexity from O(n) to O(1).
3. Misunderstanding the Ternary Expression Logic
The expression i if i % m else -i
might be confusing because it relies on Python's truthiness:
i % m
returns 0 (falsy) when divisiblei % m
returns non-zero (truthy) when not divisible
Clearer Alternative:
class Solution:
def differenceOfSums(self, n: int, m: int) -> int:
result = 0
for i in range(1, n + 1):
if i % m == 0:
result -= i # Subtract if divisible
else:
result += i # Add if not divisible
return result
4. Edge Case Handling
While the problem states n and m are positive integers, always verify:
- What happens when
m > n
? (All numbers are not divisible by m) - What happens when
m = 1
? (All numbers are divisible by m, result will be negative)
These edge cases work correctly with the given solution but understanding them helps prevent bugs in modified versions.
Which of the following array represent a max heap?
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!