2336. Smallest Number in Infinite Set
You have a set which contains all positive integers [1, 2, 3, 4, 5, ...].
Implement the SmallestInfiniteSet class:
- SmallestInfiniteSet() Initializes the SmallestInfiniteSet object to contain all positive integers.
- int popSmallest() Removes and returns the smallest integer contained in the infinite set.
- void addBack(int num) Adds a positive integer num back into the infinite set, if it is not already in the infinite set.
Example 1:
Input:
["SmallestInfiniteSet", "addBack", "popSmallest", "popSmallest", "popSmallest", "addBack", "popSmallest", "popSmallest", "popSmallest"]
[[], [2], [], [], [], [1], [], [], []]
Output:[null, null, 1, 2, 3, null, 1, 4, 5]
ExplanationSmallestInfiniteSet smallestInfiniteSet = new SmallestInfiniteSet();
smallestInfiniteSet.addBack(2); // 2 is already in the set, so no change is made.
smallestInfiniteSet.popSmallest(); // return 1, since 1 is the smallest number, and remove it from the set.
smallestInfiniteSet.popSmallest(); // return 2, and remove it from the set.
smallestInfiniteSet.popSmallest(); // return 3, and remove it from the set.
smallestInfiniteSet.addBack(1); // 1 is added back to the set.
smallestInfiniteSet.popSmallest(); // return 1, since 1 was added back to the set and
// is the smallest number, and remove it from the set.
smallestInfiniteSet.popSmallest(); // return 4, and remove it from the set.
smallestInfiniteSet.popSmallest(); // return 5, and remove it from the set.
Constraints:
- 1 <= num <= 1000
- At most 1000 calls will be made in total to popSmallest and addBack.
From: LeetCode
Link: 2336. Smallest Number in Infinite Set
Solution:
Ideas:
To implement the SmallestInfiniteSet in C, we need to maintain a data structure that allows us to efficiently find and remove the smallest number, as well as add numbers back to the set. A good choice for this task is a min-heap. However, since the numbers are from 1 to 1000 and we need to check if a number is already in the set, we can optimize this by using an array of booleans to keep track of which numbers are currently in the set.
The structure can have an integer to track the current smallest number and a boolean array to check if a number is in the set or has been removed. When popping the smallest number, we update the current smallest number to the next number that is present in the set. When adding a number back, we just update the boolean array.
Code:
c
#define MAX_NUM 1000
typedef struct {
int nextSmallest;
bool present[MAX_NUM + 1]; // to track whether a number is in the set
} SmallestInfiniteSet;
SmallestInfiniteSet* smallestInfiniteSetCreate() {
SmallestInfiniteSet* obj = malloc(sizeof(SmallestInfiniteSet));
obj->nextSmallest = 1;
for (int i = 1; i <= MAX_NUM; ++i) {
obj->present[i] = true;
}
return obj;
}
int smallestInfiniteSetPopSmallest(SmallestInfiniteSet* obj) {
int smallest = obj->nextSmallest;
obj->present[smallest] = false;
// Find the next smallest number
while (obj->nextSmallest <= MAX_NUM && !obj->present[obj->nextSmallest]) {
obj->nextSmallest++;
}
return smallest;
}
void smallestInfiniteSetAddBack(SmallestInfiniteSet* obj, int num) {
if (!obj->present[num]) {
obj->present[num] = true;
if (num < obj->nextSmallest) {
obj->nextSmallest = num;
}
}
}
void smallestInfiniteSetFree(SmallestInfiniteSet* obj) {
free(obj);
}
/**
* Your SmallestInfiniteSet struct will be instantiated and called as such:
* SmallestInfiniteSet* obj = smallestInfiniteSetCreate();
* int param_1 = smallestInfiniteSetPopSmallest(obj);
* smallestInfiniteSetAddBack(obj, num);
* smallestInfiniteSetFree(obj);
*/