Facebook Pixel

2224. Minimum Number of Operations to Convert Time

Problem Description

You are given two time strings in 24-hour format ("HH:MM"), where:

  • current represents the starting time
  • correct represents the target time you want to reach

The task is to convert current time to correct time using the minimum number of operations.

In each operation, you can add exactly one of these time increments to the current time:

  • 60 minutes (1 hour)
  • 15 minutes
  • 5 minutes
  • 1 minute

You can use any combination of these operations and repeat them as many times as needed.

For example, if current = "02:30" and correct = "04:35", you need to add 2 hours and 5 minutes total (125 minutes). The optimal approach would be:

  • Add 60 minutes twice (2 operations for 120 minutes)
  • Add 5 minutes once (1 operation for 5 minutes)
  • Total: 3 operations

The solution converts both times to total minutes since midnight, calculates the difference, then greedily uses the largest possible increments first. It divides the remaining difference by each increment size (60, 15, 5, 1) in descending order, adding the quotient to the operation count and continuing with the remainder.

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

Intuition

The key insight is that we want to minimize the total number of operations, which means we should use the largest possible increments whenever we can. This is a classic greedy approach.

Think of it like making change with coins - if you need to give 67 cents in change and you have quarters (25Β’), dimes (10Β’), nickels (5Β’), and pennies (1Β’), you'd naturally start with the largest coins first: 2 quarters, 1 dime, 1 nickel, and 2 pennies. This gives you the minimum number of coins.

The same principle applies here. We have four "time coins" of values 60, 15, 5, and 1 minutes. To bridge the gap between current and correct times with the fewest operations, we should:

  1. First, convert both times to minutes for easier calculation (hours Γ— 60 + minutes)
  2. Find the difference we need to cover
  3. Use as many 60-minute increments as possible
  4. Then use as many 15-minute increments as possible from what remains
  5. Then 5-minute increments
  6. Finally, 1-minute increments for any remainder

This greedy strategy works because each larger increment is divisible by or contains the smaller ones in a way that doesn't create conflicts. We can always break down a larger increment into smaller ones if needed, but using larger increments first guarantees fewer total operations.

For instance, if we need to add 127 minutes:

  • 127 Γ· 60 = 2 remainder 7 β†’ Use 2 operations of 60 minutes
  • 7 Γ· 15 = 0 remainder 7 β†’ Can't use 15-minute increments
  • 7 Γ· 5 = 1 remainder 2 β†’ Use 1 operation of 5 minutes
  • 2 Γ· 1 = 2 remainder 0 β†’ Use 2 operations of 1 minute
  • Total: 2 + 0 + 1 + 2 = 5 operations

Learn more about Greedy patterns.

Solution Approach

The implementation follows a straightforward greedy algorithm:

Step 1: Convert times to minutes

a = int(current[:2]) * 60 + int(current[3:])
b = int(correct[:2]) * 60 + int(correct[3:])
  • Extract hours using string slicing [:2] and minutes using [3:]
  • Convert both times to total minutes since midnight
  • For example, "14:30" becomes 14 * 60 + 30 = 870 minutes

Step 2: Calculate the difference

ans, d = 0, b - a
  • Initialize ans to track the total number of operations
  • Calculate d as the difference in minutes we need to add
  • Since we can only increase time, correct must be greater than or equal to current

Step 3: Apply greedy approach

for i in [60, 15, 5, 1]:
    ans += d // i
    d %= i
  • Iterate through increment sizes in descending order: [60, 15, 5, 1]
  • For each increment size i:
    • d // i gives the maximum number of times we can use this increment
    • Add this count to our total operations
    • Update d to the remainder using modulo operator d %= i
    • This remainder will be handled by smaller increments

Example walkthrough: If current = "11:00" and correct = "11:22":

  • Convert to minutes: a = 660, b = 682
  • Difference: d = 22
  • Process increments:
    • 60: 22 // 60 = 0, remainder = 22
    • 15: 22 // 15 = 1, remainder = 7
    • 5: 7 // 5 = 1, remainder = 2
    • 1: 2 // 1 = 2, remainder = 0
  • Total operations: 0 + 1 + 1 + 2 = 4

The algorithm has a time complexity of O(1) since we always iterate through exactly 4 increment values, and space complexity of O(1) as we only use a few variables.

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 current = "09:43" and correct = "11:01".

Step 1: Convert times to minutes

  • current = "09:43" β†’ 9 * 60 + 43 = 540 + 43 = 583 minutes
  • correct = "11:01" β†’ 11 * 60 + 1 = 660 + 1 = 661 minutes

Step 2: Calculate the difference

  • We need to add: 661 - 583 = 78 minutes
  • Initialize operation counter: ans = 0

Step 3: Apply greedy approach with increments [60, 15, 5, 1]

For 60-minute increment:

  • How many times can 60 fit into 78? 78 Γ· 60 = 1 (with remainder)
  • Add 1 operation: ans = 0 + 1 = 1
  • Remaining time: 78 % 60 = 18 minutes

For 15-minute increment:

  • How many times can 15 fit into 18? 18 Γ· 15 = 1 (with remainder)
  • Add 1 operation: ans = 1 + 1 = 2
  • Remaining time: 18 % 15 = 3 minutes

For 5-minute increment:

  • How many times can 5 fit into 3? 3 Γ· 5 = 0
  • Add 0 operations: ans = 2 + 0 = 2
  • Remaining time: 3 % 5 = 3 minutes

For 1-minute increment:

  • How many times can 1 fit into 3? 3 Γ· 1 = 3
  • Add 3 operations: ans = 2 + 3 = 5
  • Remaining time: 3 % 1 = 0 minutes

Result: We need 5 operations total:

  • 1 Γ— 60 minutes
  • 1 Γ— 15 minutes
  • 0 Γ— 5 minutes
  • 3 Γ— 1 minute

This gives us exactly 60 + 15 + 0 + 3 = 78 minutes, transforming 09:43 β†’ 11:01.

Solution Implementation

1class Solution:
2    def convertTime(self, current: str, correct: str) -> int:
3        # Convert current time from "HH:MM" format to total minutes
4        current_minutes = int(current[:2]) * 60 + int(current[3:])
5      
6        # Convert correct/target time from "HH:MM" format to total minutes
7        target_minutes = int(correct[:2]) * 60 + int(correct[3:])
8      
9        # Calculate the difference in minutes between target and current time
10        operations_count = 0
11        time_difference = target_minutes - current_minutes
12      
13        # Greedily use the largest possible time increments (60, 15, 5, 1 minutes)
14        # to minimize the number of operations needed
15        time_increments = [60, 15, 5, 1]
16      
17        for increment in time_increments:
18            # Add the number of times we can use this increment
19            operations_count += time_difference // increment
20            # Update remaining time difference
21            time_difference %= increment
22      
23        return operations_count
24
1class Solution {
2    public int convertTime(String current, String correct) {
3        // Extract hours and minutes from current time and convert to total minutes
4        int currentMinutes = Integer.parseInt(current.substring(0, 2)) * 60
5            + Integer.parseInt(current.substring(3));
6      
7        // Extract hours and minutes from correct time and convert to total minutes
8        int correctMinutes = Integer.parseInt(correct.substring(0, 2)) * 60
9            + Integer.parseInt(correct.substring(3));
10      
11        // Initialize operation counter and calculate time difference in minutes
12        int operationCount = 0;
13        int timeDifference = correctMinutes - currentMinutes;
14      
15        // Array of possible operation values in descending order (60, 15, 5, 1 minutes)
16        int[] operations = {60, 15, 5, 1};
17      
18        // Greedily use the largest possible operations first
19        for (int operation : operations) {
20            // Add the number of times we can use this operation
21            operationCount += timeDifference / operation;
22            // Update remaining time difference
23            timeDifference %= operation;
24        }
25      
26        return operationCount;
27    }
28}
29
1class Solution {
2public:
3    int convertTime(string current, string correct) {
4        // Convert time strings (HH:MM format) to total minutes
5        // Extract hours (first 2 chars) and multiply by 60, then add minutes (chars 3-4)
6        int currentMinutes = stoi(current.substr(0, 2)) * 60 + stoi(current.substr(3, 2));
7        int targetMinutes = stoi(correct.substr(0, 2)) * 60 + stoi(correct.substr(3, 2));
8      
9        // Initialize operation counter and calculate time difference
10        int operationCount = 0;
11        int timeDifference = targetMinutes - currentMinutes;
12      
13        // Define available time increments in descending order (greedy approach)
14        // Using 60, 15, 5, and 1 minute increments
15        vector<int> timeIncrements = {60, 15, 5, 1};
16      
17        // Greedily use the largest possible increments first
18        for (int increment : timeIncrements) {
19            // Add the number of times we can use this increment
20            operationCount += timeDifference / increment;
21            // Update remaining time difference
22            timeDifference %= increment;
23        }
24      
25        return operationCount;
26    }
27};
28
1function convertTime(current: string, correct: string): number {
2    // Convert time strings (HH:MM format) to total minutes
3    // Extract hours (first 2 chars) and multiply by 60, then add minutes (chars 3-4)
4    const currentMinutes: number = parseInt(current.substring(0, 2)) * 60 + parseInt(current.substring(3, 5));
5    const targetMinutes: number = parseInt(correct.substring(0, 2)) * 60 + parseInt(correct.substring(3, 5));
6  
7    // Initialize operation counter and calculate time difference
8    let operationCount: number = 0;
9    let timeDifference: number = targetMinutes - currentMinutes;
10  
11    // Define available time increments in descending order (greedy approach)
12    // Using 60, 15, 5, and 1 minute increments
13    const timeIncrements: number[] = [60, 15, 5, 1];
14  
15    // Greedily use the largest possible increments first
16    for (const increment of timeIncrements) {
17        // Add the number of times we can use this increment
18        operationCount += Math.floor(timeDifference / increment);
19        // Update remaining time difference
20        timeDifference %= increment;
21    }
22  
23    return operationCount;
24}
25

Time and Space Complexity

Time Complexity: O(1)

The algorithm performs the following operations:

  • Parsing the time strings to extract hours and minutes: O(1) since the string format is fixed (HH:MM)
  • Converting both times to minutes: O(1) with two arithmetic operations each
  • Iterating through a fixed array of 4 elements [60, 15, 5, 1]: O(4) = O(1)
  • For each iteration, performing division and modulo operations: O(1)

Since all operations are constant time and the loop runs exactly 4 times regardless of input, the overall time complexity is O(1).

Space Complexity: O(1)

The algorithm uses only a fixed amount of extra space:

  • Variables a and b to store the converted minutes: O(1)
  • Variables ans and d to track the operations count and remaining difference: O(1)
  • The array [60, 15, 5, 1] is a constant-size array: O(1)
  • Loop variable i: O(1)

No additional space that scales with input size is used, resulting in O(1) space complexity.

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

Common Pitfalls

1. Incorrect String Parsing

A common mistake is using wrong indices when extracting hours and minutes from the time string. Some might write:

  • int(current[0:1]) instead of int(current[:2]) for hours
  • int(current[2:]) instead of int(current[3:]) for minutes (forgetting the colon at index 2)

Solution: Remember the format is "HH:MM" where:

  • Hours are at indices 0-1 (use [:2])
  • Colon is at index 2
  • Minutes are at indices 3-4 (use [3:])

2. Handling Time Wraparound

The problem doesn't explicitly state whether times can wrap around midnight. Developers might incorrectly assume that if current > correct, they need to add 24 hours first:

# Incorrect assumption
if current_minutes > target_minutes:
    target_minutes += 24 * 60  # Adding a full day

Solution: Based on the problem constraints, correct time is always greater than or equal to current time within the same day. No wraparound handling is needed.

3. Using Non-Greedy Approach

Some might try to use dynamic programming or recursion unnecessarily:

# Overly complex approach
def minOperations(remaining, increments):
    if remaining == 0:
        return 0
    min_ops = float('inf')
    for inc in increments:
        if inc <= remaining:
            min_ops = min(min_ops, 1 + minOperations(remaining - inc, increments))
    return min_ops

Solution: The greedy approach always works optimally here. Using larger increments first guarantees the minimum number of operations because:

  • Any combination of smaller increments that equals a larger increment requires more operations
  • For example, 60 minutes = 4Γ—15 minutes, but using one 60-minute operation is better than four 15-minute operations

4. Integer Division vs Float Division

Using regular division / instead of integer division // will cause issues:

# Wrong - produces float
ans += d / i  # Results in 1.5 instead of 1 for 22/15

# Correct - produces integer
ans += d // i  # Results in 1 for 22/15

Solution: Always use integer division // when counting the number of complete increments that fit into the remaining time difference.

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

What is the best way of checking if an element exists in a sorted array once in terms of time complexity? Select the best that applies.


Recommended Readings

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

Load More