點陣圖
-
用 bit 組成的陣列來存放值,用 bit 狀態 1,0 代表存在不存在,取值和存值都用位運算。限制是必須為連續範圍且不能過大。
-
實現
// 初始化點陣圖大小,只支援 0 ~ n - 1 所有數字的增刪改查
void Bitset(int n);
void add(int num);
void remove(int num);
// 如果點陣圖裡沒有 num,就加入;如果有就刪除
void reverse(int nums);
bool contains(int num);
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
using namespace std;
vector<int> st;
// 初始化點陣圖大小,只支援 0 ~ n - 1 共 n 個數字的增刪改查
void Bitset(int n) {
// a / b 的結果向上取整:(a + b - 1) / b,前提都是正數
st.resize((n + 31) / 32);
}
// 加入點陣圖
// 下標從 0 開始,num 在編號為 num / 32 的 32 位 int 中,下標為 num % 32
// 1 << (num % 32) 表示把 1 左移 (num % 32) 位
void add(int num) {
st[num / 32] |= 1 << (num % 32);
}
// 刪除
void remove(int num) {
st[num / 32] &= ~(1 << (num % 32));
}
// 如果點陣圖裡沒有 num,就加入;如果有就刪除
void reverse(int num) {
st[num / 32] ^= 1 << (num % 32);
}
// 是否包含
bool contains(int num) {
return ((st[num / 32] >> (num % 32)) & 1) == 1;
}
int main() {
int n = 1000;
int testTimes = 10000;
// 點陣圖,範圍 0~999
Bitset(n);
// 自帶的 set 進行對比測試
unordered_set<int> hashSet;
srand(time(NULL));
for (int i = 0; i < testTimes; ++i) {
double decide = rand() / (double) (RAND_MAX);
// 範圍 0~999
int number = rand() % (n - 1);
if (decide < 0.333) {
add(number);
hashSet.emplace(number);
} else if (decide < 0.666) {
remove(number);
hashSet.erase(number);
} else {
reverse(number);
if (hashSet.find(number) == hashSet.end())
hashSet.emplace(number);
else
hashSet.erase(number);
}
}
bool flag = true;
for (int i = 0; i < 1000; ++i) {
if (contains(i) != (hashSet.find(i) != hashSet.end())) {
flag = false;
break;
}
}
cout << boolalpha << flag;
}
2166. 設計位集
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
using namespace std;
class Bitset {
public:
vector<int> st;
int len;
bool reversed = false;
int oneCount = 0;
int zeroCount;
Bitset(int size) {
len = size;
zeroCount = size;
st.resize((size + 31) / 32);
}
bool isOne(int idx) {
return (st[idx / 32] & (1 << (idx % 32))) != 0;
// return ((st[idx / 32] >> (idx % 32)) & 1) == 1;
}
void fix(int idx) {
if ((!reversed && !isOne(idx))
|| reversed && isOne(idx)) {
zeroCount--;
oneCount++;
reverse(idx);
}
}
void unfix(int idx) {
if ((!reversed && isOne(idx))
|| reversed && !isOne(idx)) {
zeroCount++;
oneCount--;
reverse(idx);
}
}
/* void fix(int idx) {
int index = idx / 32;
int bit = idx % 32;
if (!reversed) {
// 含義沒反轉,改成 1
if (!isOne(idx)) {
// idx 位置不是 1 的時候才要修改
zeroCount--;
oneCount++;
st[index] |= (1 << bit);
}
} else {
// 含義反轉,改成 0
if (isOne(idx)) {
// idx 位置是 1 的時候才要修改
zeroCount--;
oneCount++;
// st[index] &= ~(1 << bit);
st[index] ^= (1 << bit);
}
}
}*/
/* void unfix(int idx) {
int index = idx / 32;
int bit = idx % 32;
if (!reversed) {
// 含義沒反轉,改成 0
if (isOne(idx)) {
zeroCount++;
oneCount--;
// st[index] &= ~(1 << bit);
st[index] ^= (1 << bit);
}
} else {
// 含義反轉,改成 1
if (!isOne(idx)) {
zeroCount++;
oneCount--;
st[index] |= (1 << bit);
}
}
}*/
void reverse(int idx) {
st[idx / 32] ^= (1 << (idx % 32));
}
// 陣列中每個位其實沒有反轉,只是含義反轉了
void flip() {
reversed = !reversed;
swap(oneCount, zeroCount);
}
bool all() {
return oneCount == len;
}
bool one() {
return oneCount > 0;
}
int count() {
return oneCount;
}
string toString() {
string s;
for (int i = 0; i < len; ++i) {
char ch = '0';
if ((reversed == false && isOne(i))
|| (reversed == true && !isOne(i)))
ch = '1';
s.append(1, ch);
}
return s;
}
};