Find the bug · Easy
Fix the Bill Splitter
Easy Find the bug Seen at Stripe, Square
splitBill(totalCents, people) splits a bill in cents between people people. The shares must add up to exactly totalCents, differ by at most one cent, and be listed largest first.
Accounting found that some splits do not add up to the bill. Find the bug and fix it.
Example 1
Input: totalCents = 1000, people = 4 Output: [250, 250, 250, 250]
Example 2
Input: totalCents = 1000, people = 3 Output: [334, 333, 333] Explanation: The buggy version returns [333, 333, 333]: one cent disappears.
Constraints
1 <= people0 <= totalCents
The buggy code
function splitBill(totalCents, people) {
const share = Math.round(totalCents / people);
return new Array(people).fill(share);
}
function splitBill(totalCents: number, people: number): number[] {
const share = Math.round(totalCents / people);
return new Array(people).fill(share);
}
def split_bill(total_cents: int, people: int) -> list[int]:
share = round(total_cents / people)
return [share] * people
<?php
function splitBill(int $totalCents, int $people): array
{
$share = (int) round($totalCents / $people);
return array_fill(0, $people, $share);
}
class Solution {
public int[] splitBill(int totalCents, int people) {
int share = (int) Math.round((double) totalCents / people);
int[] out = new int[people];
Arrays.fill(out, share);
return out;
}
}
Hints
Hint 1
Add up the buggy result for 1000 split 3 ways, and for 1001 split 2 ways.
Hint 2
Integer division gives the base share; what do you do with the remainder?
Find and fix the bug
Loading the editor… (JavaScript is required to run code in your browser.)
Solution and explanation
Show the bug and the fix
Time O(n) · Space O(n)
The bug: each share is the rounded average, so the shares add up to round(total / n) x n, which is only equal to the total when n divides it. Rounding down loses cents; rounding up invents them.
The fix: give everyone total // n and hand the remainder total % n out one cent at a time to the first remainder people. This is the standard way payment systems allocate money; never split money with floating point and rounding.
Fixed version
function splitBill(totalCents, people) {
const base = Math.floor(totalCents / people);
const remainder = totalCents % people; // these people get one extra cent
return Array.from({ length: people }, (_, i) => base + (i < remainder ? 1 : 0));
}
function splitBill(totalCents: number, people: number): number[] {
const base = Math.floor(totalCents / people);
const remainder = totalCents % people; // these people get one extra cent
return Array.from({ length: people }, (_, i) => base + (i < remainder ? 1 : 0));
}
def split_bill(total_cents: int, people: int) -> list[int]:
base, remainder = divmod(total_cents, people) # `remainder` people get one extra cent
return [base + 1] * remainder + [base] * (people - remainder)
<?php
function splitBill(int $totalCents, int $people): array
{
$base = intdiv($totalCents, $people);
$remainder = $totalCents % $people; // these people get one extra cent
$out = [];
for ($i = 0; $i < $people; $i++) {
$out[] = $base + ($i < $remainder ? 1 : 0);
}
return $out;
}
class Solution {
public int[] splitBill(int totalCents, int people) {
int base = totalCents / people;
int remainder = totalCents % people; // these people get one extra cent
int[] out = new int[people];
for (int i = 0; i < people; i++) out[i] = base + (i < remainder ? 1 : 0);
return out;
}
}
Common mistakes
- Adding the remainder to the last person only (shares then differ by more than one cent).
- Using floats for money at all.
Follow-up questions
- Split by weights (60/30/10) without losing cents: the largest remainder method.
More Code Clinic: Find the Bug problems
- Fix the Binary Search · Easy
- Fix the Two Sum Hash Map · Easy
- Fix the Longest Substring Without Repeats · Medium
- Fix Merge Intervals · Medium
- Fix the Mutable Default Argument · Easy
- Fix the Substring Check · Easy