Problem overview
The function secondLargest receives three integers, a, b and c, and returns the one that is neither the largest nor the smallest. For 7, 3, 9 the answer is 7. For 12, 8, 3 it is 8.
The algorithm must run in O(1) time and use O(1) extra space. With only three numbers, sorting is not needed; a few comparisons are enough.
Approach: test each candidate
The answer is one of three numbers, so test them one at a time. A number x is the second largest when it sits between the other two: not below the smaller of them and not above the larger of them. For a that is min(b, c) <= a && a <= max(b, c).
Check a first. If it does not qualify, check b the same way. If neither does, c must be the middle value, so return it without a test. This leaves three returns and two conditions.
The comparisons use <= on both sides, so equal values are allowed. With 5, 5, 2, the first test passes, because min(5, 2) is 2, which is at most 5, and 5 is at most max(5, 2), which is 5. The function returns 5, and 5 is correct: the sorted list is 2, 5, 5.
Step by step
- Test
a. Computemin(b, c)andmax(b, c). Ifalies between them, inclusive, returna. - Test
b. Do the same withmin(a, c)andmax(a, c), and returnbif it lies between them. - Return
c. Ifaandbare not in the middle, the only remaining candidate isc, so no condition is required.
The solution in Go
func secondLargest(a, b, c int) int {
if min(b, c) <= a && a <= max(b, c) {
return a
}
if min(a, c) <= b && b <= max(a, c) {
return b
}
return c
}
Tracing 7, 3, 9: min(3, 9) is 3 and max(3, 9) is 9, and 3 <= 7 && 7 <= 9 is true, so it returns 7. Tracing 12, 8, 3: for a, the range is 3 to 8 and 12 is outside; for b, the range is 3 to 12 and 8 is inside, so it returns 8.
Some Go details:
- Built-in
minandmax. Since Go 1.21 these are part of the language, so no import is needed. They accept two or more arguments of the same ordered type, and they work onint,float64and strings. In earlier Go versions you had to write them yourself. This lesson targets Go 1.22. - Grouped parameters.
a, b, c intgives all three parameters the typeint. - Precedence. Comparisons bind tighter than
&&, so each condition reads as two comparisons joined by "and", with no extra parentheses. - Final return. The function ends with
return cinstead of a thirdif. Go demands a return at the end of a function with a result, and the logic makes the last test unnecessary.
Complexity
The function evaluates a fixed number of comparisons and calls to min and max on at most three numbers, so time is O(1). It creates no data structures, so extra space is O(1).
Edge cases and common mistakes
- Duplicates. With
5, 5, 2the answer is 5, and with5, 5, 5it is 5. The lesson counts the middle position in sorted order, not the second distinct value. - Negative numbers.
secondLargest(-1, -5, -3)returns-3. Nothing in the logic depends on sign. - Strict comparisons. Using
<instead of<=would rejectawhen it equals the smaller or larger of the others. For5, 5, 2neitheranorbwould pass, and the function would fall through toreturn cand answer 2. - Swapping the roles. For
b, the others areaandc. Writingmin(b, c)in the second test by copy-paste checks the wrong pair. - Testing only one side. A check such as
a < max(b, c)accepts the smallest number too. Both bounds are needed.
Testing
secondLargest(7, 3, 9)gives7.secondLargest(12, 8, 3)gives8.secondLargest(1, 2, 3)gives2.secondLargest(3, 2, 1)gives2.secondLargest(5, 5, 2)gives5.secondLargest(-1, -5, -3)gives-3.