點陣圖

n1ce2cv發表於2024-09-17

點陣圖

  • 用 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;
    }
};

相關文章