Problem overview
The method twoSum receives an Array[Int] named nums and an Int named target. It returns an array with the indices of two numbers that add up to target, or Array(-1, -1) if there is no such pair. The input has at most one solution, and the same index can't be used twice, although two equal values at different indices are fine.
For nums = Array(2, 7, 11, 15) and target = 9, the values at indices 0 and 1 are 2 and 7, which sum to 9. The answer is Array(0, 1). The statement asks for O(n^2) time and O(1) space.
Approach: check every pair of indices
The simplest idea is to try every pair. Pick a first index i, then pick a second index j and test whether nums(i) + nums(j) equals target. The first match is the answer.
The second index only needs to look to the right of i. A pair of positions has a left member and a right member, and the pair is tested when the outer loop reaches the left one. Looking left would repeat earlier work. Starting j at i + 1 also guarantees that an element is never paired with itself.
There are about n * (n - 1) / 2 pairs, hence O(n^2) time, and the method needs only a few variables, hence O(1) space. Faster ways exist, based on a hash map or on sorting, and other lessons on the same problem cover them. This one is about the plain nested loop.
Step by step
- Outer loop. Use
for (i <- nums.indices).nums.indicesis the range of valid positions, 0 up tonums.length - 1. Every element can be the first of the pair. - Inner loop. Use
for (j <- i + 1 until nums.size). The worduntilexcludes the upper end, sojstops at the last valid index.nums.sizeandnums.lengthgive the same number for an array. - Test the pair. If
nums(i) + nums(j) == target, returnArray(i, j). Scala indexes arrays with parentheses. - Report failure. If both loops finish with no match, return
Array(-1, -1). This line runs only after every pair has been tried.
The solution in Scala
class Solution {
def twoSum(nums: Array[Int], target: Int): Array[Int] = {
for (i <- nums.indices) {
for (j <- i + 1 until nums.size) {
if (nums(i) + nums(j) == target) {
return Array(i, j)
}
}
}
return Array(-1, -1)
}
}
Scala details:
- A
forloop is a method call. A loop withoutyieldis turned into a call offoreachwith the body as a function. Areturninside the body leaves the enclosing method,twoSum, and Scala 3.5 prints a warning that such non-local returns are no longer supported. The code still runs and returns the pair. The clean alternative isscala.util.boundarywithboundary.break, or a loop with a flag. - Ranges.
i + 1 until nums.sizeis an empty range wheniis the last index, so the inner loop simply doesn't run. - Arrays.
nums(i)is a method call,nums.apply(i). Reading an index outside the array throwsArrayIndexOutOfBoundsException; the ranges here never leave the array. Intarithmetic wraps.Intis 32 bits. Withnums = Array(2000000000, 2000000000)the sum is 4000000000, which wraps to-294967296. So fortarget = -294967296the method returnsArray(0, 1), though the true sum is a different number. For ordinary inputs this doesn't matter, but converting with.toLongwould avoid it.- The result is a new array. Printing an
Arraydirectly shows an object reference, not its contents; usemkString(", ")to see the values.
Complexity
Time: O(n^2). The inner loop makes n - 1 passes for i = 0, n - 2 for i = 1, and so on, a total of n * (n - 1) / 2 comparisons in the worst case, when no pair matches.
Space: O(1). The loops use a few integers. The returned two-element array has a fixed size.
Edge cases and common mistakes
- Empty or one-element input. The inner loop never runs, and the method returns
Array(-1, -1). - Using one index twice.
Array(3, 4)withtarget = 6returnsArray(-1, -1). Startingjatiwould pair the 3 with itself and answerArray(0, 0). - Equal values.
Array(3, 3)withtarget = 6returnsArray(0, 1). - Order of the indices. The answer comes out as
Array(i, j)withi < j. ForArray(7, 2)andtarget = 9it isArray(0, 1). - Values, not indices. The method returns positions, not the numbers that were added.
- No match.
Array(1, 2, 3)withtarget = 100returnsArray(-1, -1).
Testing
Array(2, 7, 11, 15), target 9 givesArray(0, 1).Array(3, 3), target 6 givesArray(0, 1).Array(3, 4), target 6 givesArray(-1, -1).Array(), target 6 givesArray(-1, -1).
