Next Closest Time: Simulation & Modulo Math
[!NOTE] This module explores the core principles of Next Closest Time: Simulation & Modulo Math, deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.
1. Problem Definition
Given a time represented in the format "HH:MM", form the next closest time by reusing the current digits. There is no limit on how many times a digit can be reused.
Example 1:
Input: time = "19:34"
Output: "19:39"
Explanation: The next closest time choosing from digits 1, 9, 3, 4, is 19:39, which occurs 5 minutes later.
Example 2:
Input: time = "23:59"
Output: "22:22"
Explanation: The next closest time choosing from digits 2, 3, 5, 9, is 22:22 (Next Day).
2. Interactive Analysis
Click “Find Next” to generate valid permutations and pinpoint the closest future time.
Allowed Digits
Valid Combos
3. Intuition: Bounded Brute Force
Because there are exactly 4 slots (HH:MM), and each slot can hold one of up to 4 unique numbers, the maximum number of possible combinations you can dial is 4^4 = 256.
The search space is tiny. We apply “Bounded Brute Force”:
- Generate all 256 possible times.
- Filter out invalid times (like “25:99”).
- Calculate the minutes elapsed since the starting time.
- Keep the one with the smallest positive elapsed time.
Mathematical Anchor: Modular Arithmetic
To handle the “Tomorrow” wrap-around without excessive branching:
int delta = (curr - start + 24 * 60) % (24 * 60);
If curr is smaller than start (next day), curr - start is negative. Adding 1440 (24*60) ensures the result is positive, effectively simulating the clock cycle.
4. Solutions
class Solution {
public String nextClosestTime(String time) {
int start = 60 * Integer.parseInt(time.substring(0, 2)) + Integer.parseInt(time.substring(3));
int ans = start;
int diff = 24 * 60;
Set<Integer> digits = new HashSet<>();
for (char c : time.toCharArray()) {
if (c != ':') {
digits.add(c - '0');
}
}
// Bounded O(1) Search Space (Max 256 iterations)
for (int h1 : digits) {
for (int h2 : digits) {
int hour = h1 * 10 + h2;
if (hour < 24) {
for (int m1 : digits) {
for (int m2 : digits) {
int min = m1 * 10 + m2;
if (min < 60) {
int curr = hour * 60 + min;
// Modular arithmetic directly handles midnight wrapping
int delta = (curr - start + 24 * 60) % (24 * 60);
if (delta == 0) delta = 24 * 60; // Same time maps to 24 hours later
if (delta < diff) {
ans = curr;
diff = delta;
}
}
}
}
}
}
}
return String.format("%02d:%02d", ans / 60, ans % 60);
}
}
package main
import "fmt"
func nextClosestTime(time string) string {
start := 60*(int(time[0]-'0')*10+int(time[1]-'0')) + (int(time[3]-'0')*10 + int(time[4]-'0'))
ans := start
diff := 24 * 60
digits := make(map[int]bool)
for i := 0; i < len(time); i++ {
if time[i] != ':' {
digits[int(time[i]-'0')] = true
}
}
for h1 := range digits {
for h2 := range digits {
hour := h1*10 + h2
if hour < 24 {
for m1 := range digits {
for m2 := range digits {
min := m1*10 + m2
if min < 60 {
curr := hour*60 + min
// Time wrapping math
delta := (curr - start + 24*60) % (24 * 60)
if delta == 0 {
delta = 24 * 60
}
if delta < diff {
ans = curr
diff = delta
}
}
}
}
}
}
}
return fmt.Sprintf("%02d:%02d", ans/60, ans%60)
}
5. Complexity Analysis
| Strategy | Time | Space | Notes |
|---|---|---|---|
| Bounded Brute Force | O(1) | O(1) | Max 4^4 = 256 iterations. Fits in L1 Cache. |