Problem: 2166. 设计位集
思路
这道题要求设计一个位集(Bitset)类,实现以下功能:
- 添加数字
- 删除数字
- 反转位集
- 判断位集是否全为1
- 判断位集是否至少有一个1
- 统计位集中1的个数
- 将位集转换为字符串表示
我们可以使用一个整型数组来存储位集的数据,每个整型数可以表示32个位。然后,我们可以使用位运算来实现各种功能。
解题方法
根据题目要求,我们可以设计一个
Bitset
类,其中包含以下成员变量:
set
:整型数组,用于存储位集的数据ones
:整型变量,表示位集中1的个数zeros
:整型变量,表示位集中0的个数reverse
:布尔变量,表示位集是否反转size
:整型变量,表示位集的大小
然后,我们可以实现以下方法:
fix(int idx)
:添加数字到位集中。首先,我们需要计算数字在整型数组中的索引和位偏移量。然后,根据是否反转位集,判断是否需要添加数字到位集中,并更新相应的计数器。unfix(int idx)
:从位集中删除数字。首先,我们需要计算数字在整型数组中的索引和位偏移量。然后,根据是否反转位集,判断是否需要从位集中删除数字,并更新相应的计数器。flip()
:反转位集。将reverse
变量取反,并交换ones
和zeros
的值。all()
:判断位集是否全为1。如果ones
等于位集的大小,则返回true
,否则返回false
。one()
:判断位集是否至少有一个1。如果ones
大于0,则返回true
,否则返回false
。count()
:统计位集中1的个数。直接返回ones
的值。toString()
:将位集转换为字符串表示。我们可以遍历整型数组中的每个整型数,然后将每个位的状态转换为字符,并拼接到字符串中。
复杂度
时间复杂度:添加数字和删除数字的时间复杂度为 O ( 1 ) O(1) O(1),反转位集、判断位集是否全为1、判断位集是否至少有一个1、统计位集中1的个数和将位集转换为字符串表示的时间复杂度为 O ( n ) O(n) O(n),其中 n 为位集的大小。
空间复杂度:整型数组的空间复杂度为 O ( n ) O(n) O(n),其中 n 为位集的大小。
代码
class Bitset {
public int[] set;
public int ones;
public int zeros;
public boolean reverse;
public final int size;
public Bitset(int n) {
set = new int[(n + 31) / 32];
size = n;
ones = 0;
zeros = n;
reverse = false;
}
// 添加数字
public void fix(int idx) {
int index = idx / 32;
int bit = idx % 32;
if (!reverse) {
if ((set[index] & (1 << bit)) == 0) {
zeros--;
ones++;
set[index] |= (1 << bit);
}
} else {
if ((set[index] & (1 << bit)) != 0) {
zeros--;
ones++;
set[index] ^= (1 << bit);
}
}
}
// 删除数字
public void unfix(int idx) {
int index = idx / 32;
int bit = idx % 32;
if (!reverse) {
if ((set[index] & (1 << bit)) != 0) {
ones--;
zeros++;
set[index] ^= (1 << bit);
}
} else {
if ((set[index] & (1 << bit)) == 0) {
ones--;
zeros++;
set[index] |= (1 << bit);
}
}
}
public void flip() {
reverse = !reverse;
int tmp = zeros;
zeros = ones;
ones = tmp;
}
public boolean all() {
return ones == size;
}
public boolean one() {
return ones > 0;
}
public int count() {
return ones;
}
public String toString() {
StringBuffer sb = new StringBuffer();
for (int i = 0, k = 0, number, status; i < size; k++) {
number = set[k];
for (int j = 0; j < 32 && i < size; j++, i++) {
status = (number >> j) & 1;
status ^= reverse ? 1 : 0;
sb.append(status);
}
}
return sb.toString();
}
}
/**
* Your Bitset object will be instantiated and called as such:
* Bitset obj = new Bitset(size);
* obj.fix(idx);
* obj.unfix(idx);
* obj.flip();
* boolean param_4 = obj.all();
* boolean param_5 = obj.one();
* int param_6 = obj.count();
* String param_7 = obj.toString();
*/