Start learning free

LESSON 93 OF 348 · CONDITIONAL STATEMENTS - CHALLENGES

Second Largest of Three Numbers in TypeScript: O(1)

Practice Read the full explanation

Given 3 integers, return the second largest number.

Example 1:

Input: A = 7, B = 3, C = 9
Output: 7

Example 2:

Input: A = 12, B = 8, C = 3
Output: 8

Note:

Your algorithm should run in O(1) time and use O(1) extra space.


Hints:

There are three candidates to the solution: A, B and C. We should try out each of them until we find the correct one. How can we check if A is the solution? What should happen for A to be the second largest value?

A is the second largest value if min(B, C) <= A and A <= max(B, C). We can write an if statement checking these conditions and if they hold, return A:
if A >= min(B, C) and A <= max(B, C):
	return A
What if the conditions don't hold and A is not the solution? What should we do next?

We should test B. Similarly, B is the second largest value if min(A, C) <= B and B <= max(A, C). We can write an if statement checking these conditions and if they hold, return B.
if A >= min(B, C) and A <= max(B, C):
	return A
if B >= min(A, C) and B <= max(A, C):
	return B
What if not even B is the solution?

Then, it's clear that C is the solution, so we should return C. We don't even need to check the conditions anymore:
if A >= min(B, C) and A <= max(B, C):
	return A
if B >= min(A, C) and B <= max(A, C):
	return B
return C

STEP 1 OF 3
    Ctrl + Enter to check

    TYPESCRIPT · CONDITIONAL STATEMENTS - CHALLENGES

    Second Largest Value in TypeScript, explained

    Problem overview

    The method secondLargest receives three numbers, A, B and C, and returns the one in the middle when they are ordered by size. For 7, 3, 9 the order is 3, 7, 9, so the answer is 7. For 12, 8, 3 the answer is 8.

    The task asks for O(1) time and O(1) space. With only three values, a few comparisons are enough: no sorting and no array are needed.

    Approach: test each candidate

    The answer is one of three values, so test them in turn. A number is the second largest when it is not below the smaller of the other two and not above the larger of the other two. In other words, it sits between them. For A, the condition is Math.min(B, C) <= A && A <= Math.max(B, C).

    If A passes, return it. Otherwise test B the same way against A and C. If neither passes, C must be the answer, so it needs no test. Exactly one of the three numbers is the middle one when the values are distinct, so ruling out two leaves the third.

    Work through A = 7, B = 3, C = 9. The smaller of B and C is 3 and the larger is 9. Since 3 <= 7 <= 9, A is in the middle and the method returns 7. With A = 12, B = 8, C = 3, the range for A is 3 to 8 and 12 is outside it. For B, the other two are 12 and 3, and 3 <= 8 <= 12 holds, so the method returns 8.

    Step by step

    1. Check A. Write an if whose condition has two parts joined by &&: the smaller of B and C is less than or equal to A, and A is less than or equal to the larger of them. Math.min and Math.max compute these. Inside, return A.
    2. Check B. Repeat with B against A and C, and return B when it fits.
    3. Return C. If A and B failed, C is what is left, so the method returns it without another check.

    The solution in TypeScript

    class Solution {
        secondLargest(A: number, B: number, C: number): number {
            if (Math.min(B, C) <= A && A <= Math.max(B, C)) {
                return A;
            }
            if (Math.min(A, C) <= B && B <= Math.max(A, C)) {
                return B;
            }
            return C;
        }
    }
    

    Language notes:

    • Math.min and Math.max are built-in functions that take any number of arguments and return the smallest or largest. They are called on the Math object, not on the numbers.
    • Parameter names. The capital letters A, B and C are ordinary parameter names. TypeScript convention is lowerCamelCase, but here they match the lesson.
    • Chained comparisons don't exist. In some languages, x <= A <= y means "A between x and y". In TypeScript it parses as (x <= A) <= y, comparing a boolean to a number, which the compiler reports as an error. Two comparisons joined by && are needed.
    • Annotations are erased. number is checked only by the compiler.

    Complexity

    The method makes a fixed number of comparisons and calls to Math.min and Math.max, so it runs in O(1) time and uses O(1) extra space.

    Edge cases and common mistakes

    • Duplicates. With 5, 5, 3 the sorted order is 3, 5, 5, and the second largest is 5. The method returns 5, because the comparisons use <=. With 2, 2, 2 it returns 2. With strict < instead, 5, 5, 3 would return 3, which is wrong.
    • Negative numbers. The method uses only comparisons, so -1, -5, -3 gives -3.
    • Any position. The answer can be A, B or C. Test all three: 7, 3, 9 (answer is A), 12, 8, 3 (answer is B) and 9, 3, 7 (answer is C).
    • Using sort() on an array. [A, B, C].sort() with no comparator sorts as strings, so [10, 9, 1] becomes [1, 10, 9]. A numeric sort needs (x, y) => x - y. The comparison approach in this lesson avoids the issue and the allocation.

    Testing

    • secondLargest(7, 3, 9) should give 7.
    • secondLargest(12, 8, 3) should give 8.
    • secondLargest(9, 3, 7) should give 7.
    • secondLargest(5, 5, 3) should give 5.
    • secondLargest(-1, -5, -3) should give -3.
    Keep going with TypeScriptAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free