数据结构与算法之位运算: LeetCode 2166. 设计位集 (Ts版)

设计位集

描述

  • 位集 Bitset 是一种能以紧凑形式存储位的数据结构。请你实现 Bitset 类。
    • Bitset(int size) 用 size 个位初始化 Bitset ,所有位都是 0
    • void fix(int idx) 将下标为 idx 的位上的值更新为 1 。如果值已经是 1 ,则不会发生任何改变
    • void unfix(int idx) 将下标为 idx 的位上的值更新为 0 。如果值已经是 0 ,则不会发生任何改变
    • void flip() 翻转 Bitset 中每一位上的值。换句话说,所有值为 0 的位将会变成 1 ,反之亦然
    • boolean all() 检查 Bitset 中 每一位 的值是否都是 1 。如果满足此条件,返回 true ;否则,返回 false
    • boolean one() 检查 Bitset 中 是否 至少一位 的值是 1 。如果满足此条件,返回 true ;否则,返回 false
    • int count() 返回 Bitset 中值为 1 的位的 总数
    • String toString() 返回 Bitset 的当前组成情况。注意,在结果字符串中,第 i 个下标处的字符应该与 Bitset 中的第 i 位一致

示例

输入
["Bitset", "fix", "fix", "flip", "all", "unfix", "flip", "one", "unfix", "count", "toString"]
[[5], [3], [1], [], [], [0], [], [], [0], [], []]
输出
[null, null, null, null, false, null, null, true, null, 2, "01010"]

解释

Bitset bs = new Bitset(5); // bitset = "00000".
bs.fix(3);     // 将 idx = 3 处的值更新为 1 ,此时 bitset = "00010" 。
bs.fix(1);     // 将 idx = 1 处的值更新为 1 ,此时 bitset = "01010" 。
bs.flip();     // 翻转每一位上的值,此时 bitset = "10101" 。
bs.all();      // 返回 False ,bitset 中的值不全为 1 。
bs.unfix(0);   // 将 idx = 0 处的值更新为 0 ,此时 bitset = "00101" 。
bs.flip();     // 翻转每一位上的值,此时 bitset = "11010" 。
bs.one();      // 返回 True ,至少存在一位的值为 1 。
bs.unfix(0);   // 将 idx = 0 处的值更新为 0 ,此时 bitset = "01010" 。
bs.count();    // 返回 2 ,当前有 2 位的值为 1 。
bs.toString(); // 返回 "01010" ,即 bitset 的当前组成情况。

提示

  • 1 <= size <= 1 0 5 10^5 105
  • 0 <= idx <= size - 1
  • 至多调用 fix、unfix、flip、all、one、count 和 toString 方法 总共 1 0 5 10^5 105
  • 至少调用 all、one、count 或 toString 方法一次
  • 至多调用 toString 方法 5 次

Typescript 版算法实现


1 ) 方案1:利用数组实现

class Bitset {
    private arr: number[];   // 存储每一位的数组
    private cnt: number;     // 1 的个数
    private reversed: number; // 反转操作的次数奇偶性(0 或 1)

    constructor(size: number) {
        this.arr = new Array(size).fill(0);
        this.cnt = 0;
        this.reversed = 0;
    }

    fix(idx: number): void {
        if ((this.arr[idx] ^ this.reversed) === 0) {
            this.arr[idx] ^= 1;
            this.cnt++;
        }
    }

    unfix(idx: number): void {
        if ((this.arr[idx] ^ this.reversed) === 1) {
            this.arr[idx] ^= 1;
            this.cnt--;
        }
    }

    flip(): void {
        this.reversed ^= 1;
        this.cnt = this.arr.length - this.cnt;
    }

    all(): boolean {
        return this.cnt === this.arr.length;
    }

    one(): boolean {
        return this.cnt > 0;
    }

    count(): number {
        return this.cnt;
    }

    toString(): string {
        let res = '';
        for (let bit of this.arr) {
            res += (bit ^ this.reversed).toString();
        }
        return res;
    }
}


/**
 * Your Bitset object will be instantiated and called as such:
 * var obj = new Bitset(size)
 * obj.fix(idx)
 * obj.unfix(idx)
 * obj.flip()
 * var param_4 = obj.all()
 * var param_5 = obj.one()
 * var param_6 = obj.count()
 * var param_7 = obj.toString()
 */

2 ) 方案2:另一种方式

class Bitset {
    private set: number[]; // 存储位的数组,每个元素存储32位
    private n: number;     // 总位数
    private ones: number;  // 当前1的数量
    private reverse: number; // 反转操作的次数奇偶性

    constructor(size: number) {
        this.n = size;
        this.set = new Array(Math.ceil(size / 32)).fill(0);
        this.ones = 0;
        this.reverse = 0;
    }

    fix(idx: number): void {
        const index = Math.floor(idx / 32);
        const bit = idx % 32;
        const flag = (this.set[index] >> bit) & 1;
        if ((this.reverse ^ flag) === 0) {
            this.set[index] ^= 1 << bit;
            ++this.ones;
        }
    }

    unfix(idx: number): void {
        const index = Math.floor(idx / 32);
        const bit = idx % 32;
        const flag = (this.set[index] >> bit) & 1;
        if ((this.reverse ^ flag) === 1) {
            this.set[index] ^= 1 << bit;
            --this.ones;
        }
    }

    flip(): void {
        this.reverse ^= 1;
        this.ones = this.n - this.ones;
    }

    all(): boolean {
        return this.ones === this.n;
    }

    one(): boolean {
        return this.ones > 0;
    }

    count(): number {
        return this.ones;
    }

    toString(): string {
        let res: string = '';
        for (let i = 0; i < this.n; i++) {
            const index = Math.floor(i / 32);
            const bit = i % 32;
            const flag = (this.set[index] >> bit) & 1;
            res += this.reverse ^ flag;
        }
        return res;
    }
}

/**
 * Your Bitset object will be instantiated and called as such:
 * var obj = new Bitset(size)
 * obj.fix(idx)
 * obj.unfix(idx)
 * obj.flip()
 * var param_4 = obj.all()
 * var param_5 = obj.one()
 * var param_6 = obj.count()
 * var param_7 = obj.toString()
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值