Problem overview
The method countPairs receives two positive integers, n and sum. It returns how many different pairs (x, y) satisfy 1 <= x, y <= n and x + y == sum. Two pairs that contain the same numbers in a different order count as one, so (1, 5) and (5, 1) are the same pair.
With n = 7 and sum = 6 the valid pairs are (1, 5), (2, 4) and (3, 3), so the answer is 3. The pair (3, 3) counts once: x and y may be equal. The statement asks for O(n^2) time and O(1) space.
Approach: try every candidate
This is a brute-force problem: the number of candidate pairs is small enough to test them all. The only decision is how to list the candidates without counting any pair twice.
If x and y were both allowed to range over 1 to n, every pair with different numbers would show up in both orders. Requiring x <= y fixes that: each unordered pair then has exactly one representation, with the smaller number first. The outer loop picks x from 1 to n, and the inner loop picks y from x to n. Starting the inner loop at x and not at 1 does the de-duplication, and it still allows x == y.
The number of tested pairs is about n * (n + 1) / 2, which is O(n^2). Only a handful of variables are needed, so the space is O(1).
The nested loops are not the only way. Once x is fixed, y must be exactly sum - x, so a single loop that checks whether sum - x lies between x and n would count the same pairs in O(n) time. This lesson sticks to the brute-force loops, which test every candidate and show the pattern you will reuse on harder problems.
The example, traced
For n = 7 and sum = 6, the outer loop visits i = 1 to 7, and the inner loop covers j from i up to 7:
- For
i = 1, the onlyjwith1 + j == 6is 5. Count so far: 1. - For
i = 2, the match isj = 4. Count: 2. - For
i = 3, the match isj = 3, and the inner loop starts exactly at 3, so it is found. Count: 3. - For
i = 4, the partner would be 2, but the inner loop starts at 4 and never goes back. No match. - For
i = 5,6and7, the partner would be 1, 0 and -1, all belowi, so nothing is counted.
The final value of result is 3. Every pair is found once, from its smaller member.
Step by step
- Create the counter. Declare
resultwithvarand start it at 0. It has to be avarbecause it changes; avalcouldn't be updated. - Loop over the first number. Use
i <- 1 to n. The wordtomakes a range that includesn, which is right becausexcan equaln. - Loop over the second number. Inside it, use
j <- i to n. Starting aticounts each pair once and keeps the pairs where both numbers are equal. - Test and count. When
i + j == sum, add one toresultwith+= 1. Every match is a distinct pair, so each adds exactly 1. Scala has no++operator. - Return. After the loops, write
resultas the last expression. In Scala the last expression of a method is its value, so noreturnis needed.
The solution in Scala
class Solution {
def countPairs(n: Int, sum: Int): Int = {
var result = 0
for (i <- 1 to n) {
for (j <- i to n) {
if (i + j == sum) {
result += 1
}
}
}
result
}
}
Scala details:
toversusuntil.1 to nincludesn;1 until nstops before it. Usinguntilhere would miss every pair that containsn.- The range can be empty.
1 to 0is an empty range, so a loop over it runs zero times. No special case is needed for a smalln. varand the final line.resultis read at the end like any value. The bareresulton the last line is the method's return value, and it has to be the last expression of the method.Intarithmetic.Intis 32 bits and wraps around silently.i + jcan't overflow here unlessnis close to the largestInt, and a loop of that size would be far too slow anyway.
Complexity
Time: O(n^2). For i = 1 the inner loop makes n passes, for i = 2 it makes n - 1, and so on down to 1. The total is n + (n - 1) + ... + 1, which is n * (n + 1) / 2. Each pass does constant work.
Space: O(1). The method holds result and two loop variables, whatever n is.
Edge cases and common mistakes
- Sum too small. The smallest possible sum is 1 + 1 = 2. With
sum = 1no pair works, and the method returns 0. - Sum too large. The largest sum is
n + n.countPairs(3, 100)returns 0. - Equal numbers.
countPairs(4, 8)returns 1, for(4, 4), andcountPairs(5, 2)returns 1, for(1, 1). - Starting the inner loop at 1. That counts
(1, 5)and(5, 1)separately. Forn = 7andsum = 6it gives 5 and not 3. - Starting the inner loop at
i + 1. That drops pairs with equal numbers, such as(3, 3). - Using
until n. It leaves outnitself.
Testing
countPairs(7, 6)gives3.countPairs(1, 2)gives1.countPairs(4, 8)gives1.countPairs(3, 100)gives0.
