Facebook Pixel

2437. Number of Valid Clock Times

EasyStringEnumeration
Leetcode Link

Problem Description

You have a string time of length 5 that represents a time on a digital clock in the format "hh:mm". The time can range from "00:00" (earliest) to "23:59" (latest).

Some digits in the string are replaced with the ? symbol, which means those digits are unknown. Each ? can be replaced with any digit from 0 to 9.

Your task is to count how many valid clock times can be formed by replacing all the ? symbols with digits.

For example:

  • If time = "?5:00", the ? in the hours position could be 0 or 1, giving us valid times "05:00" and "15:00", so the answer would be 2.
  • If time = "23:?", the ? in the minutes position could be any digit from 0 to 9, giving us 10 valid times from "23:00" to "23:09".
  • If time = "2?:??", we need to consider all valid combinations where the first ? can make valid hours (20-23) and the last two ? can make valid minutes (00-59).

The solution uses a brute force approach: it generates all possible times from 00:00 to 23:59 and checks each one against the given pattern. A time matches the pattern if every non-? character in the pattern equals the corresponding character in the generated time. The check function verifies this by comparing each character position - if the pattern has a ?, any digit is acceptable; otherwise, the digits must match exactly.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

When we see this problem, we need to count valid times that match a pattern with wildcards (?). The key insight is that there are only a limited number of valid times in a day - exactly 1440 different times (24 hours × 60 minutes).

Since the search space is small and well-defined, we can use a straightforward enumeration approach. Instead of trying to be clever about calculating how many possibilities each ? creates (which would require careful consideration of constraints like hours being 0-23 and minutes being 0-59), we can simply:

  1. Generate all possible valid times from 00:00 to 23:59
  2. Check each one against our pattern
  3. Count how many match

The pattern matching is simple: for each position in the time string, either the character must match exactly, or the pattern has a ? at that position (meaning any digit works).

This brute force approach is elegant because:

  • It avoids complex case analysis (like determining if ?3:?? allows hours starting with 0, 1, or 2)
  • It naturally handles all edge cases without special logic
  • The code is clean and easy to verify for correctness
  • With only 1440 possible times to check, performance is not a concern

The check function implements the pattern matching by using zip to pair up characters from the generated time and the pattern, then verifying that each pair either matches exactly or the pattern has a ? wildcard.

Solution Approach

The solution implements the enumeration strategy by iterating through all possible valid times and counting matches.

Implementation Steps:

  1. Define a helper function check(s, t):

    • Takes two strings: s (a generated time) and t (the pattern)
    • Uses zip(s, t) to pair up characters at each position
    • Returns True if for every pair (a, b), either a == b (exact match) or b == '?' (wildcard)
    • The all() function ensures every position satisfies the matching condition
  2. Generate and count valid times:

    • Use nested loops: h from 0 to 23 (hours) and m from 0 to 59 (minutes)
    • Format each time as f'{h:02d}:{m:02d}' to ensure proper two-digit formatting (e.g., 05:09 instead of 5:9)
    • Call check() to test if the generated time matches the pattern
    • Use sum() with a generator expression to count all matches

Code Walkthrough:

def countTime(self, time: str) -> int:
    def check(s: str, t: str) -> bool:
        return all(a == b or b == '?' for a, b in zip(s, t))

The check function compares two strings character by character. For time = "?5:00" and generated time "15:00":

  • Position 0: '1' vs '?''?' == '?' is True (wildcard matches)
  • Position 1: '5' vs '5''5' == '5' is True (exact match)
  • Positions 2-4: All exact matches
  • Result: True (this time is valid)
return sum(
    check(f'{h:02d}:{m:02d}', time) for h in range(24) for m in range(60)
)

This line generates all 1440 possible times (24 × 60), checks each against the pattern, and counts the matches. The generator expression avoids creating a list in memory, making the solution memory-efficient.

Time Complexity: O(1) - Always checks exactly 1440 times regardless of input Space Complexity: O(1) - Uses only a constant amount of extra space

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 walk through the solution with time = "?3:5?" to see how the algorithm works.

Step 1: Understanding what we're looking for

  • The pattern "?3:5?" has wildcards at positions 0 and 4
  • Position 0 (hours tens): ? can be 0, 1, or 2 (since the ones digit is 3)
  • Position 1 (hours ones): Must be 3
  • Position 2: Must be :
  • Position 3 (minutes tens): Must be 5
  • Position 4 (minutes ones): ? can be 0-9

Step 2: The algorithm generates and checks times

The algorithm will generate all times from 00:00 to 23:59. Let's trace through some key iterations:

When h = 3, m = 50:

  • Generated time: "03:50"
  • Check against pattern "?3:5?":
    • Position 0: '0' vs '?' → wildcard matches ✓
    • Position 1: '3' vs '3' → exact match ✓
    • Position 2: ':' vs ':' → exact match ✓
    • Position 3: '5' vs '5' → exact match ✓
    • Position 4: '0' vs '?' → wildcard matches ✓
  • Result: Match found! Count = 1

When h = 13, m = 55:

  • Generated time: "13:55"
  • Check against pattern "?3:5?":
    • Position 0: '1' vs '?' → wildcard matches ✓
    • Position 1: '3' vs '3' → exact match ✓
    • Position 2: ':' vs ':' → exact match ✓
    • Position 3: '5' vs '5' → exact match ✓
    • Position 4: '5' vs '?' → wildcard matches ✓
  • Result: Match found! Count = 2

When h = 14, m = 50:

  • Generated time: "14:50"
  • Check against pattern "?3:5?":
    • Position 0: '1' vs '?' → wildcard matches ✓
    • Position 1: '4' vs '3' → no match ✗
  • Result: No match (stops checking early due to mismatch)

Step 3: Complete enumeration

The algorithm continues checking all 1440 times. The valid matches are:

  • 03:50, 03:51, 03:52, ..., 03:59 (10 times)
  • 13:50, 13:51, 13:52, ..., 13:59 (10 times)
  • 23:50, 23:51, 23:52, ..., 23:59 (10 times)

Final answer: 30

The beauty of this approach is that we don't need to think about the constraints separately - the algorithm naturally finds all valid combinations by checking every possible time against the pattern.

Solution Implementation

1class Solution:
2    def countTime(self, time: str) -> int:
3        """
4        Count the number of valid times that can be represented by replacing '?' characters.
5      
6        Args:
7            time: A string in format "HH:MM" where some characters may be '?'
8      
9        Returns:
10            The count of all possible valid times matching the pattern
11        """
12      
13        def is_valid_match(actual_time: str, pattern: str) -> bool:
14            """
15            Check if an actual time string matches the given pattern.
16          
17            Args:
18                actual_time: A complete time string (e.g., "23:59")
19                pattern: A pattern string with possible '?' wildcards
20          
21            Returns:
22                True if the actual_time matches the pattern, False otherwise
23            """
24            # Check each character pair - they must either be equal or pattern has '?'
25            for actual_char, pattern_char in zip(actual_time, pattern):
26                if pattern_char != '?' and actual_char != pattern_char:
27                    return False
28            return True
29      
30        # Count all valid times by iterating through all possible hours and minutes
31        valid_count = 0
32      
33        # Check all 24 hours (0-23) and all 60 minutes (0-59)
34        for hour in range(24):
35            for minute in range(60):
36                # Format time as "HH:MM" with zero-padding
37                formatted_time = f'{hour:02d}:{minute:02d}'
38              
39                # Check if this time matches the pattern
40                if is_valid_match(formatted_time, time):
41                    valid_count += 1
42      
43        return valid_count
44
1class Solution {
2    /**
3     * Counts the number of valid times that can be created by replacing '?' characters
4     * in the given time string with digits.
5     * 
6     * @param time A time string in "HH:MM" format where some positions may contain '?'
7     * @return The count of all possible valid times
8     */
9    public int countTime(String time) {
10        int validTimeCount = 0;
11      
12        // Iterate through all possible hours (00-23)
13        for (int hour = 0; hour < 24; hour++) {
14            // Iterate through all possible minutes (00-59)
15            for (int minute = 0; minute < 60; minute++) {
16                // Format current hour and minute as "HH:MM"
17                String currentTime = String.format("%02d:%02d", hour, minute);
18              
19                // Check if current time matches the pattern
20                boolean isValidMatch = true;
21                for (int index = 0; index < 5; index++) {
22                    // If characters don't match and the position is not a wildcard '?'
23                    if (currentTime.charAt(index) != time.charAt(index) && 
24                        time.charAt(index) != '?') {
25                        isValidMatch = false;
26                        break;
27                    }
28                }
29              
30                // Increment count if this time is a valid match
31                if (isValidMatch) {
32                    validTimeCount++;
33                }
34            }
35        }
36      
37        return validTimeCount;
38    }
39}
40
1class Solution {
2public:
3    int countTime(string time) {
4        int validTimeCount = 0;
5      
6        // Iterate through all possible hours (00-23)
7        for (int hour = 0; hour < 24; ++hour) {
8            // Iterate through all possible minutes (00-59)
9            for (int minute = 0; minute < 60; ++minute) {
10                // Format current hour and minute as "HH:MM" string
11                char timeString[20];
12                sprintf(timeString, "%02d:%02d", hour, minute);
13              
14                // Check if current time matches the pattern
15                bool isValidMatch = true;
16                for (int i = 0; i < 5; ++i) {
17                    // If characters don't match and the pattern character is not '?'
18                    if (timeString[i] != time[i] && time[i] != '?') {
19                        isValidMatch = false;
20                        break;
21                    }
22                }
23              
24                // Increment count if this time matches the pattern
25                if (isValidMatch) {
26                    validTimeCount++;
27                }
28            }
29        }
30      
31        return validTimeCount;
32    }
33};
34
1/**
2 * Counts the number of valid time representations that match the given pattern.
3 * The pattern can contain '?' as wildcards that can be replaced with any valid digit.
4 * 
5 * @param time - A time string in "HH:MM" format where '?' represents a wildcard
6 * @returns The count of valid time combinations that match the pattern
7 */
8function countTime(time: string): number {
9    let validTimeCount = 0;
10  
11    // Iterate through all possible hours (00-23)
12    for (let hour = 0; hour < 24; hour++) {
13        // Iterate through all possible minutes (00-59)
14        for (let minute = 0; minute < 60; minute++) {
15            // Format the current time as "HH:MM" with leading zeros
16            const currentTime = `${hour}`.padStart(2, '0') + ':' + `${minute}`.padStart(2, '0');
17          
18            // Check if current time matches the pattern
19            let isValidMatch = 1;
20          
21            // Compare each character position
22            for (let position = 0; position < 5; position++) {
23                // If pattern has a specific digit and it doesn't match current time
24                if (currentTime[position] !== time[position] && time[position] !== '?') {
25                    isValidMatch = 0;
26                    break;
27                }
28            }
29          
30            // Add to count if this time matches the pattern
31            validTimeCount += isValidMatch;
32        }
33    }
34  
35    return validTimeCount;
36}
37

Time and Space Complexity

The time complexity is O(24 × 60) or O(1440), which simplifies to O(1) since it's a constant bound. The code iterates through all possible combinations of hours (24 values from 0-23) and minutes (60 values from 0-59), resulting in exactly 1440 iterations. For each iteration, the check function performs a comparison of 5 characters (the time string format "HH:MM"), which takes O(1) time. Therefore, the overall time complexity is O(24 × 60 × 1) = O(24 × 60).

The space complexity is O(1). The code uses a constant amount of extra space regardless of input. The check function creates a zip object and performs comparisons without storing additional data structures. The formatted string f'{h:02d}:{m:02d}' is created temporarily for each iteration but doesn't accumulate, maintaining constant space usage. The generator expression in the sum function also doesn't create a list but evaluates lazily, keeping space usage constant.

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

Common Pitfalls

1. Incorrect String Formatting Without Zero-Padding

A critical mistake is forgetting to zero-pad single-digit hours and minutes when generating time strings. This leads to incorrect pattern matching.

Incorrect Implementation:

# Wrong - produces "5:9" instead of "05:09"
formatted_time = f'{hour}:{minute}'

Why it fails:

  • For hour=5, minute=9, this produces "5:9" (length 3)
  • The pattern "?5:09" has length 5
  • The zip operation will only compare 3 character pairs, missing the last two digits
  • Even if lengths matched, "5:9" wouldn't align properly with the pattern positions

Correct Implementation:

# Correct - always produces "HH:MM" format
formatted_time = f'{hour:02d}:{minute:02d}'

2. Attempting to Optimize by Analyzing Pattern Positions

Developers often try to optimize by calculating possibilities for each ? position independently, but this approach is error-prone due to interdependencies.

Problematic Approach:

def countTime(self, time: str) -> int:
    # Trying to multiply individual position possibilities
    hour_tens = 3 if time[0] == '?' else 1  # Wrong logic!
    hour_ones = 10 if time[1] == '?' else 1
    # ... more calculations
    return hour_tens * hour_ones * min_tens * min_ones

Why it fails:

  • The valid range for time[0] depends on time[1]:
    • If time[1] is '0'-'3', then time[0] can be '0'-'2' (3 options)
    • If time[1] is '4'-'9', then time[0] can only be '0'-'1' (2 options)
  • Pattern "2?:00" allows only 4 valid hours (20-23), not 10

Better Solution: Stick with the brute force approach for clarity and correctness. With only 1440 possible times, optimization isn't necessary.

3. Off-by-One Errors in Range Boundaries

Using incorrect range boundaries when iterating through hours and minutes.

Incorrect:

# Wrong - includes hour 24 which doesn't exist
for hour in range(25):  
    for minute in range(60):
        # ...

# Wrong - misses the last minute (59)
for hour in range(24):
    for minute in range(59):  
        # ...

Correct:

for hour in range(24):    # 0 to 23 inclusive
    for minute in range(60):  # 0 to 59 inclusive
        # ...
Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

How would you design a stack which has a function min that returns the minimum element in the stack, in addition to push and pop? All push, pop, min should have running time O(1).


Recommended Readings

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

Load More