สมมุติว่าเราต้องการสร้างโครงสร้างข้อมูลที่รองรับการดำเนินการบางอย่าง การดำเนินการเหล่านี้จะต้องสร้างไว้ล่วงหน้าในระยะเวลา O(1) ดังนั้นให้การดำเนินการเหล่านี้เป็นเหมือน -
- insert(x):ใส่ x เข้าไปในคอลเลกชัน
- remove(x):ลบ x ออกจากคอลเล็กชัน
- getRandom():สิ่งนี้จะค้นหารูปแบบองค์ประกอบสุ่มที่คอลเลกชันนั้น
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
- สร้างตัวเลขอาร์เรย์
- สร้างหนึ่งแผนที่ m
- กำหนดฟังก์ชัน insert() ซึ่งจะใช้ val
- ret :=เมื่อ val ไม่เป็น m
- ใส่ขนาดของ nums ที่ส่วนท้ายของ m[val]
- ใส่ { val, size of m[val] – 1} คู่ที่ส่วนท้ายของ nums
- คืนสินค้า
- กำหนดฟังก์ชัน remove() ซึ่งจะใช้ val
- ret :=เมื่อ val ไม่เป็น m
- ถ้า ret ไม่ใช่ศูนย์ ดังนั้น −
- last =องค์ประกอบสุดท้ายของ nums
- m[key of last][value of last] :=องค์ประกอบสุดท้ายของ m[val]
- nums[องค์ประกอบสุดท้ายของ [m[val]] :=สุดท้าย
- ลบองค์ประกอบสุดท้ายจาก m[val]
- ถ้า m[val] ว่างเปล่า ดังนั้น −
- ลบ val จาก m
- ลบองค์ประกอบสุดท้ายออกจาก nums
- คืนสินค้า
- กำหนดฟังก์ชัน getRandom()
- ส่งคืนองค์ประกอบสุ่มหนึ่งรายการจากคอลเล็กชัน
ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -
ตัวอย่าง
#include <bits/stdc++.h>
using namespace std;
class RandomizedCollection {
public:
vector <pair <int, int>> nums;
unordered_map <int, vector<int>> m;
RandomizedCollection() {
}
bool insert(int val) {
bool ret = m.find(val) == m.end();
m[val].push_back(nums.size());
nums.push_back({val, m[val].size() - 1});
return ret;
}
bool remove(int val) {
bool ret = m.find(val) != m.end();
if(ret){
pair <int, int> last = nums.back();
m[last.first][last.second] = m[val].back();
nums[m[val].back()] = last;
m[val].pop_back();
if(m[val].empty())m.erase(val);
nums.pop_back();
}
return ret;
}
int getRandom() {
return nums[rand() % nums.size()].first;
}
};
main(){
RandomizedCollection ob;
ob.insert(10);
ob.insert(35);
ob.insert(20);
ob.insert(40);
cout << (ob.getRandom()) << endl;
ob.remove(20);
cout << (ob.getRandom()) << endl;
} อินพุต
Insert 10, 35, 20, 40, then get one random number, say 40, then remove 20, again get random element, that is say 35.
ผลลัพธ์
40 35