Problem overview
A group of n friends meets, and everybody shakes hands with everybody else, once per pair. The function countHandShakes must return how many handshakes that makes.
For n = 3, call the friends A, B and C. The handshakes are (A, B), (A, C) and (B, C), so the answer is 3. For n = 4, add D: the pairs are (A, B), (A, C), (A, D), (B, C), (B, D) and (C, D), which makes 6.
Approach
You could list all the pairs and count them, but a formula is shorter. There are two ways to reach it.
Counting from each person
Each of the n people shakes hands with the other n - 1 people, so n * (n - 1) counts every handshake. But that counts each one twice: the handshake (A, B) is counted once from A's side and once from B's side. Dividing by 2 fixes that:
handshakes = n * (n - 1) / 2
Adding up what's left
Another way to see it is to go through the people in order. A shakes hands with n - 1 others, B with n - 2 others not yet counted, and so on, down to 1 for the second to last person and 0 for the last. For n = 4 that is 3 + 2 + 1 = 6. Laid out as a grid of n - 1 rows and n columns, the handshakes fill exactly half of the cells, so the count is the grid's area divided by two, (n - 1) * n / 2. It's the same formula.
The formula involves no loop, so the answer comes in constant time however large n is.
Step by step
- Multiply
nbyn - 1. This counts every ordered pair of different people: who shakes with whom, with the direction included. - Divide by 2. This merges the two directions of each handshake into one.
- Return the result.
The division never loses anything. Of two consecutive numbers, n and n - 1, one is always even, so their product is even and halves exactly. Kotlin's integer division, which drops the remainder, therefore returns the exact count.
The solution in Kotlin
class Solution {
fun countHandShakes(n: Int): Int {
return (n * (n - 1)) / 2
}
}
Kotlin details to be aware of:
- Order of operations. The product is computed first and then divided. The parentheses around
n * (n - 1)are not required, since*and/run left to right, but they make the intent clear. - Integer division. With
Intoperands,/returns anInt. Because the product is always even, nothing is truncated here. - Division first would be wrong. Writing
n / 2 * (n - 1)truncates before multiplying: forn = 3it computes1 * 2 = 2, not 3.
Complexity
The function does a fixed number of arithmetic operations, so time is O(1) and extra space is O(1). Counting the pairs one by one with nested loops would take O(n²) time.
Edge cases and common mistakes
- One person or nobody. With
n = 1the formula gives 0, because there is nobody to shake hands with. Withn = 0it also gives 0, because the product is 0. - Two people.
n = 2gives2 * 1 / 2 = 1: one handshake. - Forgetting to halve.
n * (n - 1)alone gives 6 forn = 3instead of 3. - Overflow. An
Intin Kotlin is 32 bits, and arithmetic that goes past its range wraps around silently. The productn * (n - 1)exceeds 2147483647 oncenreaches 46342, even though the true answer would still fit. Forn = 100000this function returns 704982704, while the real count is 4999950000. A solution for such inputs would compute withLong. This lesson's signature usesInt, so keep that, and stay aware of the limit.
Testing
countHandShakes(3)returns3.countHandShakes(4)returns6.countHandShakes(1)returns0.countHandShakes(2)returns1.