Char数组上的累积BitWise OR
Cumulative BitWise OR on Char Array
我有一个大小为7K的长char数组。
char arr[] = "1110010011....." ; // length 7K
我必须对窗口大小为3的数组执行累积OR。这意味着:
arr[0] | arr[1] | arr[2] ;
arr[1] | arr[2] | arr[3] ;
什么是最好的方法?我可以比O(n)
做得更少,或者即使复杂性是O(n)
,我们如何使它更快?
如果将零一数组重新打包为一个位集,则可以更快地完成。它将快大约32倍,但仍然需要O(N)时间。此外,您可以在64位机器上使用64位单词,然后您将获得64倍的改进。
然而,请注意,对于大型N,内存带宽将成为主要瓶颈,因此只能实现8倍的改进(因为大小减少了8倍)。
这是示例代码:
int main() {
char arr[] = "01000001011111000110010000011000111";
int n = strlen(arr);
//preparation: convert to bitset
uint32_t bitset[sizeof(arr) / 32 + 3] = {0};
for (int i = 0; i < n; i++)
bitset[i/32] ^= (arr[i]=='1') << (i % 32);
//solution: bit operations
uint32_t result[sizeof(bitset) / sizeof(bitset[0])] = {0};
for (int i = 0; i < (n + 31) / 32; i++) {
uint32_t curr = bitset[i], next = bitset[i+1];
result[i] = curr | (curr >> 1) | (next << 31) | (curr >> 2) | (next << 30);
}
printf("%sn ", arr);
for (int i = 0; i < n+2; i++)
printf("%d", (result[i/32] >> (i%32)) & 1);
}
更新
对于可变窗口宽度W,上述方法花费O(N W)时间。对于小的W,它是最快的,但对于大的W 注意,对于任何窗口大小,问题都可以在O(N)时间内解决。例如,您可以在O(N)时间内预先计算零/一数组的前缀和。然后,对于每个窗口,可以将O(1)时间内窗口内的个数确定为两个和值的差。因此,您得到了一个简单的O(N)解决方案。它不使用任何位集,是真正大的W的最快方法。 对于中等窗口大小(如W=16),可以修改基于位集的方法,使其在O(N log W)时间内工作,这可能比O(N W)版本更快。这种方法有点类似于并行还原。以下是W=13的示例代码:for (int i = 0; i < (n + 31) / 32; i++) {
uint64_t curr = *(uint64_t*)&bitset[i];
curr |= (curr >> 1);
curr |= (curr >> 2);
curr |= (curr >> 4);
curr |= (curr >> 5);
result[i] = uint32_t(curr);
}
如果你有一个大小为N的数组,它只包含0和1,并且你想要对每个K个项目进行"或"运算的结果(其中K是窗口大小),那么你所要做的就是跟踪最后一个"1"在哪里。
int last1 = -1;
int range_start = 0;
int range_end = window_size - 1;
for (int i = 0; i < array_size; ++i)
{
if (a[i] == '1')
{
last1 = i;
}
if (i == range_end)
{
if (last1 >= range_start)
// output 1
else
// output 0
}
++range_start;
++range_end;
}
这里的想法是,如果窗口中有一个或多个1,那么任何窗口大小的累积OR都将为1。如果窗口包含所有0,则结果为0。
您可以通过在单独的循环中查看第一个window_size - 1
值来对其进行一点优化,从而消除range_end
变量,但这会使循环稍微复杂一些。我不知道这是否会是一场净胜球。
为了澄清,您希望输出数组中有n个元素,每个元素的值为arr[n-1]|arr[n]|arr[n+1]。(第一个和最后一个元素可能除外,它们分别没有arr[n-1]和arr[n+1]。
如果这是正确的,那么在小于O(n)的时间内不可能做到这一点。您需要至少查看数组中的每个元素一次,这单独需要O(n)时间。
幸运的是,即使是最天真的方法也能达到O(n)的目标:
int size = strlen(arr);
char arr2[size];
for (int i=1; i<size-1; i++) { //ignore first and last element
if (arr[i-1] == '1' || arr[i] == '1' || arr[i+2] == '1') {
arr2[i] = '1';
} else {
arr2[i] = '0';
}
}
在这一点上,你必须决定你所说的"高效"是什么意思。您需要决定是要减少比较还是减少分配。根据您的情况,这两种方法中的任何一种都可能是有效的选择,并会产生非常不同的解决方案。
- 瓦尔格林德:数学函数"Conditional jump or move depends on uninitialised value(s)"
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- Android NDK clang 编译器错误在 Windows 上显示'No such file or directory'
- 模式"allocate memory or use existing data"
- N-API include an .so or dll
- 已解决 - C++ 的崇高文本中的"fatal error: opencv: no such file or directory"
- 将 OR 逻辑运算符从 C++ 转换为 Fortran
- CPP 中的瓦尔格林德和记忆泄漏:"Conditional jump or move depends on uninitialised values"
- 我如何将 OR 与 if 语句一起使用字符串
- 将 if 语句中的字符与 or 进行比较
- Google Or-Tools Glop:如何创建指向 const 对象的指针数组?
- 当初始值设定项是基类名时'initializer does not name a non-static data member or base class'错误
- "No such file or directory" C++标头问题
- 处理 std::enable_if<...中谓词的逻辑"OR">
- C++ 虽然语句不适用于字符串和"or"
- 我在 #include < bits/stdc++h.> 放置时出错"No such file or directory"
- Python Bitwise OR
- Char数组上的累积BitWise OR
- 在这种情况下,'addition'和'bitwise or'是一样的吗?