Facebook Pixel

539. Minimum Time Difference

Problem Description

You are given a list of time points in 24-hour format as strings in the format "HH:MM", where HH represents hours (00-23) and MM represents minutes (00-59). Your task is to find the minimum difference in minutes between any two time points in the list.

For example, if you have time points ["23:59", "00:00"], the minimum difference would be 1 minute (from 23:59 to 00:00 the next day).

The key insight is that time is circular - after 23:59 comes 00:00, so you need to consider both the forward difference and the "wrap-around" difference when comparing times.

The solution converts each time point to total minutes since midnight (e.g., "13:14" becomes 13 × 60 + 14 = 794 minutes), sorts these values, and then checks the differences between consecutive times. To handle the circular nature of time, it also adds the first time plus 1440 minutes (24 hours) to the end of the sorted list, allowing the comparison between the last and first times across the day boundary.

Since there are only 1440 possible distinct minute values in a 24-hour period (24 × 60), if the input has more than 1440 time points, there must be duplicates, meaning the minimum difference is 0.

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

Intuition

The first observation is that working with time strings like "HH:MM" is cumbersome for comparison. Converting them to a single unit (total minutes from midnight) makes calculations much simpler. For instance, "02:30" becomes 2 × 60 + 30 = 150 minutes.

Once we have all times as minutes, finding the minimum difference between any two times seems like we need to check all pairs - but that would be inefficient. The key insight is that the minimum difference will always occur between two times that are adjacent when sorted. Why? Because if times A and C have time B between them when sorted, the difference between A and C will always be larger than both A-B and B-C differences.

So we sort the times and check consecutive pairs. However, there's a catch - time is circular! The difference between 23:50 and 00:10 isn't 23 × 60 + 40 = 1420 minutes, but rather 20 minutes (going forward from 23:50 to 00:10 the next day).

To handle this circular nature elegantly, we add the first time point plus 1440 (24 hours in minutes) to the end of our sorted list. This creates a "virtual" next-day occurrence of the earliest time, allowing us to calculate the wrap-around difference between the last and first times naturally as part of checking consecutive pairs.

The optimization about checking if there are more than 1440 time points comes from the pigeonhole principle - there are only 1440 possible minute values in a day, so if we have more time points than that, at least two must be identical, giving us a minimum difference of 0.

Learn more about Math and Sorting patterns.

Solution Approach

Let's walk through the implementation step by step:

Step 1: Early Return for Duplicates

if len(timePoints) > 1440:
    return 0

Since there are only 24 × 60 = 1440 possible distinct minute values in a 24-hour period, if we have more than 1440 time points, the pigeonhole principle guarantees duplicates exist, so we return 0 immediately.

Step 2: Convert Time Strings to Minutes

nums = sorted(int(x[:2]) * 60 + int(x[3:]) for x in timePoints)

We convert each time string to minutes using a list comprehension:

  • x[:2] extracts the hours (first two characters)
  • x[3:] extracts the minutes (characters after the colon)
  • Hours are multiplied by 60 and added to minutes to get total minutes from midnight
  • The result is immediately sorted in ascending order

For example, "13:14" becomes 13 × 60 + 14 = 794 minutes.

Step 3: Handle Circular Time

nums.append(nums[0] + 1440)

To handle the wrap-around case (e.g., the difference between 23:59 and 00:01), we append the smallest time plus 1440 minutes (24 hours) to the end of the sorted list. This creates a virtual "next day" occurrence of the earliest time.

Step 4: Find Minimum Difference

return min(b - a for a, b in pairwise(nums))

Using the pairwise function (which pairs consecutive elements), we calculate the difference between each pair of adjacent times in the sorted list. The min function returns the smallest difference among all pairs.

The pairwise function generates pairs like (nums[0], nums[1]), (nums[1], nums[2]), ..., (nums[n-1], nums[n]) where the last pair includes our appended wrap-around value.

This approach ensures we check all meaningful adjacent differences, including the circular difference between the last and first times, in O(n log n) time due to sorting.

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 an example with timePoints = ["23:59", "00:00", "12:30", "23:45"].

Step 1: Check for duplicates

  • We have 4 time points, which is less than 1440, so we continue.

Step 2: Convert to minutes and sort

  • "23:59" → 23 × 60 + 59 = 1439 minutes
  • "00:00" → 0 × 60 + 0 = 0 minutes
  • "12:30" → 12 × 60 + 30 = 750 minutes
  • "23:45" → 23 × 60 + 45 = 1425 minutes

After sorting: nums = [0, 750, 1425, 1439]

Step 3: Handle circular time

  • Append the first time + 1440: 0 + 1440 = 1440
  • Now: nums = [0, 750, 1425, 1439, 1440]

Step 4: Calculate consecutive differences

  • Pair 1: (0, 750) → difference = 750 - 0 = 750 minutes
  • Pair 2: (750, 1425) → difference = 1425 - 750 = 675 minutes
  • Pair 3: (1425, 1439) → difference = 1439 - 1425 = 14 minutes
  • Pair 4: (1439, 1440) → difference = 1440 - 1439 = 1 minute

The last pair (1439, 1440) represents the wrap-around difference between "23:59" and "00:00" the next day. Without the circular handling, we might incorrectly calculate this as 1439 - 0 = 1439 minutes!

Result: The minimum difference is 1 minute (between "23:59" and "00:00").

Solution Implementation

1class Solution:
2    def findMinDifference(self, timePoints: List[str]) -> int:
3        # If there are more than 1440 time points (total minutes in a day),
4        # by pigeonhole principle, at least two must be the same
5        if len(timePoints) > 1440:
6            return 0
7      
8        # Convert all time strings to minutes since midnight and sort them
9        # For "HH:MM" format: extract hours (first 2 chars) * 60 + minutes (chars 3-4)
10        minutes_list = sorted(int(time[:2]) * 60 + int(time[3:]) for time in timePoints)
11      
12        # Add the first time + 1440 (24 hours) to handle circular difference
13        # This accounts for the wrap-around case (e.g., 23:59 to 00:01)
14        minutes_list.append(minutes_list[0] + 1440)
15      
16        # Find the minimum difference between consecutive times
17        # pairwise creates pairs of consecutive elements: (a, b), (b, c), (c, d)...
18        from itertools import pairwise
19        return min(b - a for a, b in pairwise(minutes_list))
20
1class Solution {
2    public int findMinDifference(List<String> timePoints) {
3        // If there are more than 1440 time points (24 * 60 minutes in a day),
4        // by pigeonhole principle, at least two must be the same
5        if (timePoints.size() > 1440) {
6            return 0;
7        }
8      
9        int n = timePoints.size();
10        // Create array with size n+1 to store converted minutes and handle circular case
11        int[] minutesArray = new int[n + 1];
12      
13        // Convert each time point from "HH:MM" format to total minutes
14        for (int i = 0; i < n; i++) {
15            String[] timeParts = timePoints.get(i).split(":");
16            int hours = Integer.parseInt(timeParts[0]);
17            int minutes = Integer.parseInt(timeParts[1]);
18            minutesArray[i] = hours * 60 + minutes;
19        }
20      
21        // Sort the time points in ascending order
22        Arrays.sort(minutesArray, 0, n);
23      
24        // Add the first time point + 1440 minutes (24 hours) to handle circular difference
25        // This helps calculate the difference between the last and first time point
26        minutesArray[n] = minutesArray[0] + 1440;
27      
28        // Initialize minimum difference with a large value (2^30)
29        int minDifference = 1 << 30;
30      
31        // Find the minimum difference between consecutive time points
32        for (int i = 1; i <= n; i++) {
33            int currentDifference = minutesArray[i] - minutesArray[i - 1];
34            minDifference = Math.min(minDifference, currentDifference);
35        }
36      
37        return minDifference;
38    }
39}
40
1class Solution {
2public:
3    int findMinDifference(vector<string>& timePoints) {
4        // If there are more than 1440 time points (minutes in a day),
5        // by pigeonhole principle, at least two must be the same
6        if (timePoints.size() > 1440) {
7            return 0;
8        }
9      
10        int n = timePoints.size();
11        // Create array to store time points in minutes, with extra space for wraparound
12        vector<int> minutesArray(n + 1);
13      
14        // Convert each time point from "HH:MM" format to total minutes
15        for (int i = 0; i < n; ++i) {
16            int hours = stoi(timePoints[i].substr(0, 2));
17            int minutes = stoi(timePoints[i].substr(3, 2));
18            minutesArray[i] = hours * 60 + minutes;
19        }
20      
21        // Sort the time points in ascending order
22        sort(minutesArray.begin(), minutesArray.begin() + n);
23      
24        // Add the first time point + 1440 minutes (24 hours) to handle circular wraparound
25        // This helps calculate the difference between the last and first time points
26        minutesArray[n] = minutesArray[0] + 1440;
27      
28        // Find the minimum difference between consecutive time points
29        int minDifference = INT_MAX;
30        for (int i = 1; i <= n; ++i) {
31            minDifference = min(minDifference, minutesArray[i] - minutesArray[i - 1]);
32        }
33      
34        return minDifference;
35    }
36};
37
1/**
2 * Finds the minimum time difference between any two time points in minutes
3 * @param timePoints - Array of time strings in "HH:MM" format
4 * @returns The minimum difference in minutes between any two time points
5 */
6function findMinDifference(timePoints: string[]): number {
7    // If there are more than 1440 time points (total minutes in a day),
8    // by pigeonhole principle, at least two must be the same
9    if (timePoints.length > 1440) {
10        return 0;
11    }
12  
13    const timePointCount: number = timePoints.length;
14    // Create array with extra slot for circular comparison
15    const minutesArray: number[] = new Array(timePointCount + 1);
16  
17    // Convert all time strings to minutes since midnight
18    for (let i = 0; i < timePointCount; i++) {
19        const [hours, minutes] = timePoints[i].split(':').map(Number);
20        minutesArray[i] = hours * 60 + minutes;
21    }
22  
23    // Sort times in ascending order
24    minutesArray.sort((a, b) => a - b);
25  
26    // Add first time + 1440 (24 hours) to handle circular difference
27    // This allows comparison between last and first time across midnight
28    minutesArray[timePointCount] = minutesArray[0] + 1440;
29  
30    // Initialize minimum difference with a large value (2^30)
31    let minimumDifference: number = 1 << 30;
32  
33    // Compare each adjacent pair of times to find minimum difference
34    for (let i = 1; i <= timePointCount; i++) {
35        minimumDifference = Math.min(minimumDifference, minutesArray[i] - minutesArray[i - 1]);
36    }
37  
38    return minimumDifference;
39}
40

Time and Space Complexity

Time Complexity: O(n log n), where n is the number of time points.

The algorithm performs the following operations:

  • Converting each time string to minutes takes O(n) time, iterating through all n time points
  • Sorting the converted time values takes O(n log n) time using Python's built-in sort
  • Appending one element to the list takes O(1) time
  • Finding the minimum difference using pairwise iterates through n+1 pairs, taking O(n) time

The dominant operation is sorting, making the overall time complexity O(n log n).

Space Complexity: O(n), where n is the number of time points.

The algorithm uses:

  • A list nums to store the converted minute values, requiring O(n) space
  • The sorted operation in Python creates a new list, using O(n) additional space
  • The pairwise function creates an iterator that uses O(1) space
  • The generator expression for minimum calculation uses O(1) space

The total space complexity is O(n).

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

Common Pitfalls

1. Forgetting the Circular Nature of Time

The most common mistake is only checking differences between consecutive sorted times without considering the wrap-around from the last time to the first time across midnight.

Incorrect approach:

def findMinDifference(self, timePoints: List[str]) -> int:
    minutes_list = sorted(int(time[:2]) * 60 + int(time[3:]) for time in timePoints)
    # WRONG: Only checks consecutive pairs, misses wrap-around
    return min(minutes_list[i+1] - minutes_list[i] for i in range(len(minutes_list)-1))

This would fail for input like ["00:00", "23:59"] where the minimum difference is 1 minute (going forward from 23:59 to 00:00), not 1439 minutes (going backward).

Solution: Always append minutes_list[0] + 1440 to handle the circular case, ensuring you check the difference between the last and first times across the day boundary.

2. Not Handling Duplicate Times Efficiently

Another pitfall is not recognizing that duplicate times should immediately return 0, or worse, not realizing that more than 1440 time points guarantees duplicates.

Inefficient approach:

def findMinDifference(self, timePoints: List[str]) -> int:
    minutes_list = sorted(int(time[:2]) * 60 + int(time[3:]) for time in timePoints)
    # Inefficient: Converts and sorts everything even when duplicates are guaranteed
    for i in range(1, len(minutes_list)):
        if minutes_list[i] == minutes_list[i-1]:
            return 0
    # ... continue with normal logic

Solution: Check if len(timePoints) > 1440: return 0 at the very beginning to avoid unnecessary conversions and sorting when duplicates are guaranteed by the pigeonhole principle.

3. Incorrect Time String Parsing

Be careful with string slicing indices when parsing the time format.

Common mistakes:

# WRONG: Using wrong indices
minutes = int(time[0:2]) * 60 + int(time[2:4])  # Missing the colon, gets wrong minutes

# WRONG: Not converting to int before arithmetic
minutes = time[:2] * 60 + time[3:]  # String concatenation instead of arithmetic

Solution: Use the correct slicing time[:2] for hours and time[3:] for minutes (skipping the colon at index 2), and ensure conversion to int before performing arithmetic operations.

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

What does the following code do?

1def f(arr1, arr2):
2  i, j = 0, 0
3  new_arr = []
4  while i < len(arr1) and j < len(arr2):
5      if arr1[i] < arr2[j]:
6          new_arr.append(arr1[i])
7          i += 1
8      else:
9          new_arr.append(arr2[j])
10          j += 1
11  new_arr.extend(arr1[i:])
12  new_arr.extend(arr2[j:])
13  return new_arr
14
1public static List<Integer> f(int[] arr1, int[] arr2) {
2  int i = 0, j = 0;
3  List<Integer> newArr = new ArrayList<>();
4
5  while (i < arr1.length && j < arr2.length) {
6      if (arr1[i] < arr2[j]) {
7          newArr.add(arr1[i]);
8          i++;
9      } else {
10          newArr.add(arr2[j]);
11          j++;
12      }
13  }
14
15  while (i < arr1.length) {
16      newArr.add(arr1[i]);
17      i++;
18  }
19
20  while (j < arr2.length) {
21      newArr.add(arr2[j]);
22      j++;
23  }
24
25  return newArr;
26}
27
1function f(arr1, arr2) {
2  let i = 0, j = 0;
3  let newArr = [];
4  
5  while (i < arr1.length && j < arr2.length) {
6      if (arr1[i] < arr2[j]) {
7          newArr.push(arr1[i]);
8          i++;
9      } else {
10          newArr.push(arr2[j]);
11          j++;
12      }
13  }
14  
15  while (i < arr1.length) {
16      newArr.push(arr1[i]);
17      i++;
18  }
19  
20  while (j < arr2.length) {
21      newArr.push(arr2[j]);
22      j++;
23  }
24  
25  return newArr;
26}
27

Recommended Readings

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

Load More