GREEDY › PART I
Open — the attempt gate is not wired up yet
This editorial is meant to unlock after you have run the problem at least once, with the worked solution behind one further deliberate click. That needs per-learner unlock state nothing stores today, so for now the whole article is open.
Try it yourself first →Choose one value as the value that will fill the array. Every occurrence of that value can spread one position to the left and one position to the right per second. The positions between two consecutive occurrences therefore form empty stretches that are filled inward from both ends.
A stretch with gap positions between its boundary occurrences needs ceil(gap / 2) seconds, because the two boundaries fill it simultaneously. The value is fully spread only when its largest gap is filled, so the largest gap determines that value's required time. Finally, try every value and keep the smallest required time.
| MEASURE | BOUND | WHY |
|---|---|---|
| Time | O(n) | The first scan inserts each index once. Later, each stored occurrence participates in exactly one gap computation for its value, including the wraparound gap for the last occurrence, so no index is processed more than a constant number of times. |
| Space | O(n) extra | The hash map and all position vectors together store exactly n indices, with O(n) additional buckets and vector metadata in the worst case when values are mostly distinct. The returned integer is required output and is excluded from the working-space bound. |
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;
class Solution {
public:
int minimumSeconds(vector<int>& nums) {
int n = nums.size();
unordered_map<int, vector<int>> pos;
for (int i = 0; i < n; ++i) {
pos[nums[i]].push_back(i);
}
int ans = n;
for (auto& [value, indices] : pos) {
int maxGap = 0;
for (int i = 0; i < static_cast<int>(indices.size()); ++i) {
int gap;
if (i + 1 < static_cast<int>(indices.size())) {
gap = indices[i + 1] - indices[i] - 1;
} else {
gap = (n - indices.back() - 1) + indices.front();
}
maxGap = max(maxGap, gap);
}
int seconds = (maxGap + 1) / 2;
ans = min(ans, seconds);
}
return ans;
}
};The position of the wraparound calculation is important. For the last occurrence, there is no later index in the vector, but the circle still has one more consecutive pair: the last occurrence followed by the first occurrence after crossing the boundary. The expression adds the empty tail and empty head, without counting either boundary occurrence itself.