Facebook Pixel

1736. Latest Time by Replacing Hidden Digits

Problem Description

You are given a time string in the format hh:mm where some digits are hidden and replaced with the character ?. Your task is to find the latest (maximum) valid time possible by replacing all the ? characters with appropriate digits.

The valid time must be between 00:00 and 23:59 (inclusive), following the 24-hour format where:

  • Hours range from 00 to 23
  • Minutes range from 00 to 59

For example, if the input is "2?:?0", you should return "23:50" as this is the latest valid time you can create by replacing the ? characters.

The strategy is to maximize each digit position from left to right:

  • For the first hour digit (position 0): It can be at most 2, but if the second hour digit is 4 or greater, it can only be 1
  • For the second hour digit (position 1): It can be at most 9 if the first digit is 0 or 1, but only up to 3 if the first digit is 2
  • For the first minute digit (position 3): It can be at most 5
  • For the second minute digit (position 4): It can be at most 9
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

Since we want the latest (maximum) possible time, we should try to maximize each digit position from left to right. The key insight is that each digit has constraints based on its position and potentially on the values of other digits.

Think about how time works in 24-hour format:

  • Hours can range from 00 to 23
  • Minutes can range from 00 to 59

This means each position has a maximum possible value, but these maximums are interdependent. For the hour digits, if we have 2 as the first digit, the second digit can only go up to 3 (giving us 23). But if the first digit is 0 or 1, the second digit can go all the way up to 9.

The greedy approach works here because we process digits from left to right, and each position's maximum value depends only on positions we've already determined or can peek at. When we encounter a ?, we want to place the largest valid digit possible at that position.

For the hour positions:

  • If the first digit is ? and the second digit is 4 or higher, we can only use 1 (since 24, 25, etc. are invalid)
  • If the first digit is ? and the second digit is 3 or lower (or also ?), we can use 2
  • If the second digit is ? and the first digit is 2, we can only use up to 3
  • If the second digit is ? and the first digit is less than 2, we can use up to 9

For the minute positions, it's simpler:

  • The first minute digit can be at most 5 (since minutes go up to 59)
  • The second minute digit can always be 9 when it's ?

This greedy strategy guarantees the maximum time because we're maximizing the most significant digits first, which has the greatest impact on the overall value.

Learn more about Greedy patterns.

Solution Approach

The implementation uses a greedy approach to process each character of the time string sequentially. We convert the string to a list for easier manipulation since strings are immutable in Python.

Here's the step-by-step implementation:

  1. Convert string to list: t = list(time) allows us to modify individual characters.

  2. Process the first hour digit (index 0):

    if t[0] == '?':
        t[0] = '1' if '4' <= t[1] <= '9' else '2'
    • If the second hour digit is between 4 and 9, we can only use 1 (since 24:xx or higher would be invalid)
    • Otherwise, we use 2 to maximize the hour value
  3. Process the second hour digit (index 1):

    if t[1] == '?':
        t[1] = '3' if t[0] == '2' else '9'
    • If the first hour digit is 2, the maximum second digit is 3 (giving us 23)
    • Otherwise (when first digit is 0 or 1), we can use 9
  4. Process the first minute digit (index 3):

    if t[3] == '?':
        t[3] = '5'
    • The maximum value is 5 since minutes range from 00 to 59
  5. Process the second minute digit (index 4):

    if t[4] == '?':
        t[4] = '9'
    • This can always be 9 to maximize the minutes
  6. Return the result: return ''.join(t) converts the list back to a string.

The algorithm runs in O(1) time complexity since we're processing a fixed-length string of 5 characters. The space complexity is also O(1) as we only create a list of constant size.

Note that we skip index 2 since it's always a colon : and never needs replacement.

Ready to land your dream job?

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

Start Evaluator

Example Walkthrough

Let's walk through the example "2?:?0" to see how our greedy approach finds the maximum time "23:50".

Initial state: t = ['2', '?', ':', '?', '0']

Step 1 - Process first hour digit (index 0):

  • t[0] = '2' (not a ?, so we skip this step)
  • State remains: ['2', '?', ':', '?', '0']

Step 2 - Process second hour digit (index 1):

  • t[1] = '?', so we need to replace it
  • Check t[0]: it's '2'
  • Since the first hour digit is '2', we can only use up to '3' to keep the hour valid (≀ 23)
  • Set t[1] = '3'
  • State becomes: ['2', '3', ':', '?', '0']

Step 3 - Process first minute digit (index 3):

  • t[3] = '?', so we need to replace it
  • For minutes to be valid (00-59), the first minute digit can be at most '5'
  • Set t[3] = '5'
  • State becomes: ['2', '3', ':', '5', '0']

Step 4 - Process second minute digit (index 4):

  • t[4] = '0' (not a ?, so we skip this step)
  • State remains: ['2', '3', ':', '5', '0']

Step 5 - Convert back to string:

  • Join the list: ''.join(t) = "23:50"

The algorithm successfully found the maximum valid time by greedily maximizing each ? position while respecting the constraints of valid 24-hour time format.

Solution Implementation

1class Solution:
2    def maximumTime(self, time: str) -> str:
3        # Convert string to list for mutation
4        time_list = list(time)
5      
6        # Handle first hour digit (tens place of hour)
7        # Can be '2' if second digit is 0-3 or '?', otherwise must be '1'
8        if time_list[0] == '?':
9            if time_list[1] == '?' or time_list[1] <= '3':
10                time_list[0] = '2'
11            else:
12                time_list[0] = '1'
13      
14        # Handle second hour digit (ones place of hour)
15        # Can be '3' if first digit is '2', otherwise can be '9'
16        if time_list[1] == '?':
17            if time_list[0] == '2':
18                time_list[1] = '3'
19            else:
20                time_list[1] = '9'
21      
22        # Handle first minute digit (tens place of minute)
23        # Maximum valid value is '5' (for 59 minutes)
24        if time_list[3] == '?':
25            time_list[3] = '5'
26      
27        # Handle second minute digit (ones place of minute)
28        # Maximum valid value is '9' (for X9 minutes)
29        if time_list[4] == '?':
30            time_list[4] = '9'
31      
32        # Convert list back to string and return
33        return ''.join(time_list)
34
1class Solution {
2    public String maximumTime(String time) {
3        // Convert the time string to a character array for easier manipulation
4        char[] timeArray = time.toCharArray();
5      
6        // Handle the first digit of hours (tens place)
7        if (timeArray[0] == '?') {
8            // If second digit is 4-9, first digit can only be 1 (max would be 19)
9            // Otherwise, first digit can be 2 (max would be 23)
10            timeArray[0] = (timeArray[1] >= '4' && timeArray[1] <= '9') ? '1' : '2';
11        }
12      
13        // Handle the second digit of hours (ones place)
14        if (timeArray[1] == '?') {
15            // If first digit is 2, max second digit is 3 (to make 23)
16            // Otherwise, max second digit is 9 (to make 09, 19)
17            timeArray[1] = (timeArray[0] == '2') ? '3' : '9';
18        }
19      
20        // Handle the first digit of minutes (tens place)
21        if (timeArray[3] == '?') {
22            // Maximum value for tens place of minutes is 5 (59 minutes max)
23            timeArray[3] = '5';
24        }
25      
26        // Handle the second digit of minutes (ones place)
27        if (timeArray[4] == '?') {
28            // Maximum value for ones place of minutes is 9
29            timeArray[4] = '9';
30        }
31      
32        // Convert the character array back to a string and return
33        return new String(timeArray);
34    }
35}
36
1class Solution {
2public:
3    string maximumTime(string time) {
4        // Handle the first digit of hours (tens place)
5        // If it's '?', we need to determine the maximum valid value
6        if (time[0] == '?') {
7            // If the second digit is between '4' and '9', the first digit can only be '1'
8            // (since valid hours are 00-23, we can't have 24-29)
9            // Otherwise, we can use '2' to maximize the hour value
10            time[0] = (time[1] >= '4' && time[1] <= '9') ? '1' : '2';
11        }
12      
13        // Handle the second digit of hours (ones place)
14        // If it's '?', we need to determine the maximum valid value
15        if (time[1] == '?') {
16            // If the first digit is '2', we can only go up to '3' (for 23:xx)
17            // Otherwise (first digit is 0 or 1), we can use '9' to maximize
18            time[1] = (time[0] == '2') ? '3' : '9';
19        }
20      
21        // Handle the first digit of minutes (tens place)
22        // Maximum value is '5' (since minutes range from 00-59)
23        if (time[3] == '?') {
24            time[3] = '5';
25        }
26      
27        // Handle the second digit of minutes (ones place)
28        // Maximum value is always '9' (for x9 minutes)
29        if (time[4] == '?') {
30            time[4] = '9';
31        }
32      
33        return time;
34    }
35};
36
1/**
2 * Given a time string with some digits replaced by '?', returns the maximum valid time
3 * that can be obtained by replacing all '?' characters with digits.
4 * Time format is "HH:MM" where HH is 00-23 and MM is 00-59.
5 * 
6 * @param time - A time string in "HH:MM" format where some digits may be replaced by '?'
7 * @return The maximum valid time string after replacing all '?' characters
8 */
9function maximumTime(time: string): string {
10    // Convert string to array for easier character manipulation
11    const timeArray: string[] = Array.from(time);
12  
13    // Handle first digit of hour (tens place)
14    // If first digit is '?', it can be '2' if second digit is 0-3, otherwise '1'
15    if (timeArray[0] === '?') {
16        timeArray[0] = timeArray[1] >= '4' && timeArray[1] <= '9' ? '1' : '2';
17    }
18  
19    // Handle second digit of hour (ones place)
20    // If second digit is '?', it can be '3' if first digit is '2', otherwise '9'
21    if (timeArray[1] === '?') {
22        timeArray[1] = timeArray[0] === '2' ? '3' : '9';
23    }
24  
25    // Handle first digit of minute (tens place)
26    // Maximum value is '5' for valid minutes (00-59)
27    if (timeArray[3] === '?') {
28        timeArray[3] = '5';
29    }
30  
31    // Handle second digit of minute (ones place)
32    // Maximum value is always '9' for ones place
33    if (timeArray[4] === '?') {
34        timeArray[4] = '9';
35    }
36  
37    // Join the array back into a string and return
38    return timeArray.join('');
39}
40

Time and Space Complexity

The time complexity is O(1) because the algorithm performs a fixed number of operations regardless of input. The code examines and potentially modifies exactly 4 character positions (indices 0, 1, 3, and 4) in the time string, with each position requiring at most one comparison and one assignment operation. Converting the string to a list with list(time) takes O(5) time since the time format is always "HH:MM" (5 characters), and joining the list back to a string with ''.join(t) also takes O(5) time. Since all operations are constant, the overall time complexity is O(1).

The space complexity is O(1) because the algorithm uses a fixed amount of extra space. The list t created from the input string always contains exactly 5 characters (for the "HH:MM" format), which is a constant amount of space that doesn't scale with any input parameter. No additional data structures are created that depend on input size, making the space complexity constant at O(1).

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

Common Pitfalls

1. Incorrect Order of Evaluation for Hour Digits

The Pitfall: A critical mistake occurs when determining the first hour digit without properly checking the second hour digit. The code checks if time_list[1] <= '3', but this comparison is problematic when time_list[1] is a non-? character between '4' and '9'.

Consider the input "?4:15":

  • The condition time_list[1] <= '3' performs string comparison: '4' <= '3' evaluates to False (correct by luck)
  • However, the logic if time_list[1] == '?' or time_list[1] <= '3' is semantically incorrect because we're comparing characters, not integers

Why This Happens: Python compares strings lexicographically, so '4' <= '3' returns False, but this works accidentally. The real issue is conceptual - we should be comparing numeric values or characters explicitly.

2. The Correct Solution

class Solution:
    def maximumTime(self, time: str) -> str:
        time_list = list(time)
      
        # Handle first hour digit - check second digit properly
        if time_list[0] == '?':
            # Check if second digit forces us to use '1'
            if time_list[1] in '456789':
                time_list[0] = '1'
            else:
                # Second digit is '?', '0', '1', '2', or '3'
                time_list[0] = '2'
      
        # Handle second hour digit
        if time_list[1] == '?':
            if time_list[0] == '2':
                time_list[1] = '3'
            else:
                time_list[1] = '9'
      
        # Handle first minute digit
        if time_list[3] == '?':
            time_list[3] = '5'
      
        # Handle second minute digit
        if time_list[4] == '?':
            time_list[4] = '9'
      
        return ''.join(time_list)

Key Improvements:

  • Uses in '456789' for explicit character checking rather than ambiguous string comparison
  • Makes the logic clearer: if the second hour digit is 4 or higher, we must use '1' for the first digit
  • Avoids relying on string comparison behavior that might not be immediately obvious to readers

3. Alternative Robust Approach

For even better clarity, you could convert to integers when needed:

if time_list[0] == '?':
    if time_list[1] != '?' and int(time_list[1]) >= 4:
        time_list[0] = '1'
    else:
        time_list[0] = '2'

This approach explicitly handles the numeric comparison and makes the intent crystal clear.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

A person thinks of a number between 1 and 1000. You may ask any number questions to them, provided that the question can be answered with either "yes" or "no".

What is the minimum number of questions you needed to ask so that you are guaranteed to know the number that the person is thinking?


Recommended Readings

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

Load More