思路:
这道题起始很简单就是说每次抽取一个数,然后把这个数消去再下一次随机抽取。
这里思路有两种:一是如果抽到这个数,就不需要把它从数组中删除,而是将他的值和最后一个元素的值进行互换,然后把SIZE - 1,这样就不需要用set,list这种,可以直接用下标访问元素,很快;或者如果说这个数的值是发生改变了的,利用一个数组存储发生改变后的值,然后再返回答案;二是利用分块的思想,我们不是要求第几个大于0的数嘛,这就是很明显的分块思想,每一块都是根号m * n个数,用cnt[i]表示第i块中0的数量,这样只要找到第一个sum[i - 1] < x < sum[i]的就可以了
代码:
思路一:
class Solution { public: // vector<int> cur; unordered_map<int, int> book; // vector<int> src; int sz; int _n; int src = 0; Solution(int m, int n) { _n = n; // end = m * n - 1; // cur.resize(m * n); // for(int i = 0;i<=end;i++){ // // src.push_back(i); // cur[i] = i; // } sz = src = m * n; } vector<int> flip() { int idx = next(); vector<int> ans; if(book.count(idx)){ ans = {book[idx] / _n, book[idx] % _n}; }else{ ans = {idx / _n, idx % _n}; } if(book.count(sz - 1)){ book[idx] = book[sz - 1]; }else{ book[idx] = sz - 1; } sz--; return ans; } void reset() { // cur = src; sz = src; book.clear(); } inline int next(){ return rand() % sz; } }; /** * Your Solution object will be instantiated and called as such: * Solution* obj = new Solution(m, n); * vector<int> param_1 = obj->flip(); * obj->reset(); */
思路二:
class Solution { public: Solution(int m, int n) { this->m = m; this->n = n; total = m * n; bucketSize = sqrt(m * n); for (int i = 0; i < total; i += bucketSize) { buckets.push_back({}); } srand(time(nullptr)); } vector<int> flip() { int x = rand() % total; int sumZero = 0; int curr = 0; total--; for (auto & bucket : buckets) { if (sumZero + bucketSize - bucket.size() > x) { for (int i = 0; i < bucketSize; ++i) { if (!bucket.count(curr + i)) { if (sumZero == x) { bucket.emplace(curr + i); return {(curr + i) / n, (curr + i) % n}; } sumZero++; } } } curr += bucketSize; sumZero += bucketSize - bucket.size(); } return {}; } void reset() { for (auto & bucket : buckets) { bucket.clear(); } total = m * n; } private: int m; int n; int bucketSize; int total; vector<unordered_set<int>> buckets; };