Facebook Pixel

1796. Second Largest Digit in a String

EasyHash TableString
Leetcode Link

Problem Description

You are given an alphanumeric string s that contains lowercase English letters and digits. Your task is to find the second largest numerical digit that appears in the string.

The problem asks you to:

  • Scan through the string and identify all digit characters (0-9)
  • Find the second largest unique digit among them
  • Return this second largest digit as an integer
  • If there is no second largest digit (for example, if the string has no digits, only one unique digit, or all digits are the same), return -1

For example:

  • If s = "abc123", the digits are 1, 2, 3. The largest is 3 and the second largest is 2, so return 2
  • If s = "abc111", there's only one unique digit (1), so return -1
  • If s = "abc", there are no digits, so return -1

The solution uses two variables a and b to track the largest and second largest digits respectively. As it iterates through the string:

  • When a digit larger than the current largest is found, the previous largest becomes the second largest
  • When a digit between the second largest and largest is found, it updates the second largest
  • This ensures we always maintain the top two unique digit values
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

To find the second largest digit, we need to keep track of the top two distinct digits we've seen so far. Think of it like maintaining a leaderboard with only two positions - first place and second place.

The key insight is that we don't need to collect all digits first and then sort them. Instead, we can maintain just two variables as we scan through the string once. This is similar to finding the maximum element in an array, but extended to track the top two elements.

As we encounter each digit character, there are three possible scenarios:

  1. The digit is larger than our current largest - in this case, our current largest gets "bumped down" to become the second largest, and this new digit becomes the largest
  2. The digit is between our second largest and largest - it becomes our new second largest
  3. The digit is smaller than or equal to our second largest - we ignore it as it doesn't affect our top two

The elegant part of this approach is the update logic: when we find a new maximum with v > a, we can update both values in one go with a, b = v, a. This simultaneously promotes the old maximum to second place and installs the new maximum.

We initialize both tracking variables to -1 because this serves as both a sentinel value (indicating "no digit found yet") and conveniently matches our required return value when no second largest exists. This eliminates the need for special case handling at the end.

Solution Approach

We implement a one-pass algorithm that scans through the string once while maintaining two variables to track the largest and second largest digits.

Initialization:

  • Set a = -1 to track the largest digit found
  • Set b = -1 to track the second largest digit found
  • Using -1 as initial values since it's both our "not found" indicator and the required return value when no second largest exists

Main Loop: For each character c in the string s:

  1. Check if c is a digit using c.isdigit()
  2. If it's a digit, convert it to integer v = int(c)
  3. Apply the update logic:
    • Case 1: If v > a (found a new maximum):
      • Update both values: a, b = v, a
      • This moves the old largest to second place and installs the new largest
    • Case 2: If b < v < a (found a value between second and first):
      • Update only the second largest: b = v
      • This improves our second largest without affecting the first
    • Case 3: If v <= b or v == a:
      • Do nothing, as this digit doesn't improve our top two

Return Result: After traversing the entire string, return b which contains:

  • The second largest digit if it exists
  • -1 if no second largest digit was found

The algorithm handles edge cases naturally:

  • If the string has no digits, both a and b remain -1
  • If only one unique digit exists, b remains -1
  • Duplicate digits are handled correctly since we use strict inequality checks

Time Complexity: O(n) where n is the length of the string - we traverse it once Space Complexity: O(1) - we only use two variables regardless of input size

Ready to land your dream job?

Unlock your dream job with a 3-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's trace through the example s = "dfa12321afd" to see how our algorithm finds the second largest digit.

Initial State:

  • a = -1 (largest digit)
  • b = -1 (second largest digit)

Step-by-step iteration:

  1. c = 'd': Not a digit, skip. State: a = -1, b = -1

  2. c = 'f': Not a digit, skip. State: a = -1, b = -1

  3. c = 'a': Not a digit, skip. State: a = -1, b = -1

  4. c = '1': Is a digit! v = 1

    • Check: v > a? → 1 > -1? Yes!
    • Update: a, b = 1, -1
    • State: a = 1, b = -1
  5. c = '2': Is a digit! v = 2

    • Check: v > a? → 2 > 1? Yes!
    • Update: a, b = 2, 1
    • State: a = 2, b = 1
  6. c = '3': Is a digit! v = 3

    • Check: v > a? → 3 > 2? Yes!
    • Update: a, b = 3, 2
    • State: a = 3, b = 2
  7. c = '2': Is a digit! v = 2

    • Check: v > a? → 2 > 3? No
    • Check: b < v < a? → 2 < 2 < 3? No (v equals b)
    • No update needed
    • State: a = 3, b = 2
  8. c = '1': Is a digit! v = 1

    • Check: v > a? → 1 > 3? No
    • Check: b < v < a? → 2 < 1 < 3? No
    • No update needed
    • State: a = 3, b = 2
  9. c = 'a': Not a digit, skip. State: a = 3, b = 2

  10. c = 'f': Not a digit, skip. State: a = 3, b = 2

  11. c = 'd': Not a digit, skip. State: a = 3, b = 2

Final Result: Return b = 2

The algorithm correctly identifies that among the digits {1, 2, 3}, the second largest is 2. Notice how when we encountered the digit '2' again in step 7, we didn't update our variables since it was already tracked as our second largest.

Solution Implementation

1class Solution:
2    def secondHighest(self, s: str) -> int:
3        # Initialize variables to track the highest and second highest digits
4        # Using -1 as sentinel value (no valid digit found)
5        highest = second_highest = -1
6      
7        # Iterate through each character in the string
8        for char in s:
9            # Check if the current character is a digit
10            if char.isdigit():
11                # Convert the digit character to integer
12                digit_value = int(char)
13              
14                # If current digit is greater than the highest seen so far
15                if digit_value > highest:
16                    # Update both: previous highest becomes second highest
17                    second_highest = highest
18                    highest = digit_value
19                # If current digit is between second highest and highest (exclusive)
20                elif second_highest < digit_value < highest:
21                    # Update second highest
22                    second_highest = digit_value
23      
24        # Return the second highest digit (-1 if not found)
25        return second_highest
26
1class Solution {
2    /**
3     * Finds the second highest digit in a string.
4     * 
5     * @param s the input string containing alphanumeric characters
6     * @return the second highest digit, or -1 if it doesn't exist
7     */
8    public int secondHighest(String s) {
9        // Initialize variables to track the highest and second highest digits
10        int highestDigit = -1;
11        int secondHighestDigit = -1;
12      
13        // Iterate through each character in the string
14        for (int index = 0; index < s.length(); index++) {
15            char currentChar = s.charAt(index);
16          
17            // Check if the current character is a digit
18            if (Character.isDigit(currentChar)) {
19                // Convert character digit to integer value
20                int digitValue = currentChar - '0';
21              
22                // Update highest and second highest based on current digit
23                if (digitValue > highestDigit) {
24                    // Current digit becomes new highest, previous highest becomes second
25                    secondHighestDigit = highestDigit;
26                    highestDigit = digitValue;
27                } else if (digitValue > secondHighestDigit && digitValue < highestDigit) {
28                    // Current digit is between second highest and highest
29                    secondHighestDigit = digitValue;
30                }
31            }
32        }
33      
34        // Return the second highest digit (or -1 if not found)
35        return secondHighestDigit;
36    }
37}
38
1class Solution {
2public:
3    int secondHighest(string s) {
4        // Initialize variables to track the highest and second highest digits
5        // -1 indicates no valid digit found yet
6        int highest = -1;
7        int secondHighest = -1;
8      
9        // Iterate through each character in the string
10        for (char& ch : s) {
11            // Check if the current character is a digit
12            if (isdigit(ch)) {
13                // Convert character digit to integer value
14                int digitValue = ch - '0';
15              
16                // Update highest and second highest values accordingly
17                if (digitValue > highest) {
18                    // New highest found, previous highest becomes second highest
19                    secondHighest = highest;
20                    highest = digitValue;
21                } else if (digitValue > secondHighest && digitValue < highest) {
22                    // Found a value between second highest and highest
23                    // Update second highest only
24                    secondHighest = digitValue;
25                }
26                // Note: If digitValue equals highest or is less than secondHighest,
27                // no update is needed
28            }
29        }
30      
31        // Return the second highest digit found, or -1 if it doesn't exist
32        return secondHighest;
33    }
34};
35
1/**
2 * Finds the second highest digit in a string
3 * @param s - Input string containing characters and digits
4 * @returns The second highest digit, or -1 if not found
5 */
6function secondHighest(s: string): number {
7    // Initialize tracking variables for highest and second highest digits
8    let highestDigit: number = -1;
9    let secondHighestDigit: number = -1;
10  
11    // Iterate through each character in the string
12    for (const char of s) {
13        // Check if the character is a digit (0-9)
14        if (char >= '0' && char <= '9') {
15            // Convert character to its numeric value
16            const digitValue: number = char.charCodeAt(0) - '0'.charCodeAt(0);
17          
18            // Update highest and second highest values accordingly
19            if (digitValue > highestDigit) {
20                // New highest found: shift current highest to second highest
21                secondHighestDigit = highestDigit;
22                highestDigit = digitValue;
23            } else if (digitValue !== highestDigit && digitValue > secondHighestDigit) {
24                // New second highest found (not equal to highest)
25                secondHighestDigit = digitValue;
26            }
27        }
28    }
29  
30    return secondHighestDigit;
31}
32

Time and Space Complexity

The time complexity is O(n), where n is the length of the string s. This is because the algorithm iterates through each character in the string exactly once using a single for loop. Each operation inside the loop (checking if a character is a digit, converting to integer, and comparing/updating variables) takes constant time O(1).

The space complexity is O(1). The algorithm only uses a fixed amount of extra space regardless of the input size - specifically two integer variables a and b to track the highest and second-highest digits, and a temporary variable v to store the current digit value. The space usage does not grow with the size of the input string.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

Pitfall 1: Not Handling Duplicate Digits Correctly

The Problem: A common mistake is updating the second highest when encountering a digit equal to the current highest. This leads to incorrect results when the largest digit appears multiple times.

Incorrect Implementation:

if digit_value >= highest:  # Wrong: using >= instead of >
    second_highest = highest
    highest = digit_value

Example Where It Fails:

  • Input: "abc9d9ef2"
  • Expected output: 2 (digits are 9, 9, 2)
  • Incorrect output: 9 (due to setting second_highest = 9 when seeing the second 9)

Correct Solution: Use strict inequality (>) to ensure we only update when finding a truly larger value:

if digit_value > highest:  # Correct: strict inequality
    second_highest = highest
    highest = digit_value

Pitfall 2: Using a Set to Collect All Digits First

The Problem: While using a set seems intuitive for finding unique digits, it requires extra space and two passes through the data.

Inefficient Approach:

digits = set()
for char in s:
    if char.isdigit():
        digits.add(int(char))
sorted_digits = sorted(digits, reverse=True)
return sorted_digits[1] if len(sorted_digits) >= 2 else -1

Issues:

  • Space complexity increases to O(10) for the set
  • Time complexity becomes O(n + 10log10) due to sorting
  • Less elegant and more code

Better Solution: The two-variable tracking approach maintains O(1) space and O(n) time while being more concise.

Pitfall 3: Forgetting the Boundary Condition for Second Highest Update

The Problem: When updating the second highest, forgetting to check that the new value is also less than the highest can lead to incorrect results.

Incorrect Implementation:

elif digit_value > second_highest:  # Wrong: missing upper bound check
    second_highest = digit_value

Example Where It Fails:

  • Input: "a5b5c5"
  • After seeing first 5: highest = 5, second_highest = -1
  • After seeing second 5: Without the upper bound check, we might incorrectly set second_highest = 5
  • Result: Returns 5 instead of -1

Correct Solution: Always check both bounds:

elif second_highest < digit_value < highest:  # Correct: check both bounds
    second_highest = digit_value
Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

Which algorithm should you use to find a node that is close to the root of the tree?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More