681. Next Closest Time
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.
You may assume the given input string is always valid. For example, “01:34”, “12:09” are all valid. “1:34”, “12:9” are all invalid.
Example 1:
Input: “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. It is not 19:33, because this occurs 23 hours and 59 minutes later.
Example 2:
Input: “23:59”
Output: “22:22”
Explanation: The next closest time choosing from digits 2, 3, 5, 9, is 22:22. It may be assumed that the returned time is next day’s time since it is smaller than the input time numerically.
方法0: brute force
discussion: https://leetcode.com/problems/next-closest-time/discuss/107783/C%2B%2BJava-Clean-Code
思路:
首先这道题有特殊性,因为一天最多有1440分,暴力枚举并转化成时间,然后检查是否符合要求只需要O(1)时间。
class Solution {
int mins[4] = { 600, 60, 10, 1 };
public:
string nextClosestTime(string time) {
size_t colon = time.find(':');
int cur = stoi(time.substr(0, colon)) * 60 + stoi(time.substr(colon + 1));
string next = "0000";
for (int i = 1, d = 0; i <= 1440 && d < 4; i++) {
int m = (cur + i) % 1440;
for (d = 0; d < 4; d++) {
next[d] = '0' + m / mins[d]; m %= mins[d];
if (time.find(next[d]) == string::npos) break;
}
}
return next.substr(0, 2) + ':' + next.substr(2, 2);
}
};
方法1:
discussion: https://leetcode.com/problems/next-closest-time/discuss/171365/C%2B%2B-concise-solution-with-explanation-time-O(1)-space-O(1)-using-set-(100)
思路:
每一个数位上最多有4个可能的数字,一共也只有4 ^ 4种可能,可以暴力枚举。但是在选择顺序上是可以优化的:每一次我们都会从最末一位开始向上寻找可替代的数字,直到找到第一个符合要求的解就可以直接返回。那么就分为两种情况:1. 只要当前位向上转一下就可以找到合法解,条件有更大的数字可以选,且如果是小时位的话不超过24,如果是分钟位的话不超过60,2. 要不然就没有更大数字,要不然向上转一下就会超出某个限制范围,这个时候必须将本位回调到最小数字,这样当前面变成更大数字时才能保证后面最小。
Complexity
Time complexity: O(1)
Space complexity: O(1)
class Solution {
public:
string nextClosestTime(string time) {
set<int> digits;
for (char c: time) if (isdigit(c)) digits.insert(c);
for (int i = time.size() - 1; i >= 0; i--) {
if (!isdigit(time[i])) continue;
auto it = upper_bound(digits.begin(), digits.end(), time[i]);
if (it != digits.end()) {
time[i] = *it;
if (i >= 3 && stoi(time.substr(3, 2)) < 60 || i < 2 && stoi(time.substr(0, 2)) < 24)
return time;
}
time[i] = *digits.begin();
}
return time;
}
};