Algorithm
Number Division
Mathematics
Equal Parts
Whole Numbers

Algo for dividing a number into almost equal whole numbers

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Dividing an integer into almost equal whole-number parts is a standard quotient-and-remainder problem. If you need k integer parts whose sum is n and whose values differ by at most 1, the optimal construction is simple: distribute the remainder across some of the parts. This gives the most balanced result possible under integer constraints.

Use Quotient and Remainder

The key observation is that integer division already tells you the balanced baseline.

Let:

  • 'q = n // k'
  • 'r = n % k'

Then:

  • 'r parts should be q + 1'
  • 'k - r parts should be q'

This works because the extra remainder units are spread one at a time across the first r buckets. No two parts differ by more than 1, which is the best you can do.

For example, if n = 17 and k = 5:

  • 'q = 3'
  • 'r = 2'

So the answer is:

4, 4, 3, 3, 3

Those add up to 17, and the largest difference between any two parts is 1.

A Simple Python Implementation

python
1def split_almost_equally(n: int, k: int) -> list[int]:
2    if k <= 0:
3        raise ValueError("k must be positive")
4
5    q, r = divmod(n, k)
6    return [q + 1] * r + [q] * (k - r)
7
8print(split_almost_equally(17, 5))
9print(split_almost_equally(10, 3))

This is enough for most applications such as load distribution, pagination, or evenly splitting work into chunks.

Why This Is Optimal

Suppose two parts differed by 2 or more. You could subtract 1 from the larger part and add 1 to the smaller part, making the partition more balanced while keeping the same total sum. Therefore any optimal near-equal partition must have maximum difference 0 or 1.

That immediately forces the quotient-and-remainder construction. There is no more balanced whole-number solution.

Control Ordering Based on the Use Case

The mathematical solution does not require any special order, but applications often do. Sometimes you want larger parts first. Other times you want them spread out.

For example, to distribute the larger parts across positions rather than grouping them at the front, you can assign them round-robin.

python
1def split_spread_out(n: int, k: int) -> list[int]:
2    parts = [n // k] * k
3    for i in range(n % k):
4        parts[i] += 1
5    return parts
6
7print(split_spread_out(17, 5))

This example still returns the same multiset of values, but the distribution logic is easy to adapt if the target system cares about bucket position.

Handle Edge Cases Explicitly

Several edge cases matter in real code:

  • 'k <= 0: invalid input'
  • 'k > n: some parts may be zero if zero-sized parts are allowed'
  • negative n: define whether the problem even allows it

If you need strictly positive parts, then k cannot exceed n when n is nonnegative. That is a different constraint from the basic whole-number problem.

python
1def split_positive_parts(n: int, k: int) -> list[int]:
2    if n < k:
3        raise ValueError("cannot create strictly positive parts")
4
5    base = split_almost_equally(n - k, k)
6    return [x + 1 for x in base]
7
8print(split_positive_parts(17, 5))

Here each part is at least 1, and the balancing logic is applied to the remaining amount.

Common Use Cases

This pattern appears in many places:

  • splitting rows across worker threads
  • distributing budget units across teams
  • assigning pages to batch jobs
  • sharding records into buckets

Because the formula is exact and cheap, there is rarely a need for search or optimization libraries.

Common Pitfalls

  • Overcomplicating the problem when quotient and remainder already give the balanced solution.
  • Forgetting to validate k > 0.
  • Ignoring whether zero-valued parts are allowed.
  • Assuming there is a unique order, when usually only the multiset of part sizes matters.
  • Writing ad hoc loops that drift from the exact sum instead of preserving n precisely.

Summary

  • The balanced whole-number split of n into k parts comes from integer division.
  • Use n // k as the base size and distribute n % k extra units one at a time.
  • The resulting parts differ by at most 1, which is optimal.
  • Check whether your use case allows zero-sized parts or requires all parts to be positive.
  • This is a direct arithmetic solution, not a search problem.

Course illustration
Course illustration

All Rights Reserved.