C# 位模式中真值的前n个位置

C# 位模式中真值的前n个位置,c#,C#,我有一个100位的位模式。程序将改变模式中的位为真或假。在任何给定的时间,我都需要找到第一个“n”真值的位置。例如,如果模式如下 10011001000 位为真的前3个索引是0、3、4 位为真的前4个索引是0、3、4、7 我可以有一个列表,但是firstntrue(int)的复杂性将是O(n)。是否有改进性能的方法?没有 当然,除非您在更改发生时截取更改,并维护“前100个”列表。否 当然,除非您在发生更改时截取它们,并维护“前100个”列表。不,没有办法改进O(n)。这可以从数学上证明不,没有

我有一个100位的位模式。程序将改变模式中的位为真或假。在任何给定的时间,我都需要找到第一个“n”真值的位置。例如,如果模式如下

10011001000

位为真的前3个索引是0、3、4 位为真的前4个索引是0、3、4、7

我可以有一个列表,但是firstntrue(int)的复杂性将是O(n)。是否有改进性能的方法?

没有

当然,除非您在更改发生时截取更改,并维护“前100个”列表。


当然,除非您在发生更改时截取它们,并维护“前100个”列表。

不,没有办法改进O(n)。这可以从数学上证明

不,没有办法提高O(n)。这可以从数学上证明

没有额外的数据结构,复杂性就无法降低,因为在最坏的情况下,您需要扫描整个列表。

没有额外的数据结构,复杂性就无法降低,因为在最坏的情况下,您需要扫描整个列表。

对于“n”项,您最多必须检查“n”次,即O(n)!
如果不进行任何拦截,也不知道它们是如何变化的,你怎么能期望减少这种情况?!

对于“n”项,你最多要检查“n”次,即O(n)!

如果不进行任何拦截,也不知道它们是如何变化的,你怎么能期望降低这种复杂性呢?

不,如果你只有一个普通数组,你就无法提高复杂性

如果只有很少的1:s到很多的0:s,则可以通过一个常数因子来提高性能,但仍然是O(n)

如果可以将位数组视为字节数组(甚至是int32数组),则可以在检查每个位之前检查每个字节(如果字节>0)


如果1位小于1:8,则可以将其实现为稀疏数组,而不是存储所有1:s的索引。

否,如果只有普通数组,则无法提高复杂性

如果只有很少的1:s到很多的0:s,则可以通过一个常数因子来提高性能,但仍然是O(n)

如果可以将位数组视为字节数组(甚至是int32数组),则可以在检查每个位之前检查每个字节(如果字节>0)


如果小于1:8的1位,可以将其实现为一个稀疏数组,而不是存储所有1:s的索引的
List

我假设在搜索时列表没有改变,但它会一直改变,直到你决定搜索,然后你就开始做你的事情

每个字节有2^8=256个0和1的组合。这里有100/8=13个字节要检查

因此,您可以构建一个包含256个条目的查找表。键是您正在位流中检查的字节的当前实际值,值是您查找的数据(一个包含1位位置的元组)。因此,如果给它5,它将返回{0,2}。此查找的成本是恒定的,内存使用量非常小

现在,当您遍历位流时,您可以一次处理一个字节的数据(而不是一次处理一个字节),只需跟踪当前字节数(当然从0开始),并将8*当前字节数添加到返回的元组中的值中。因此,现在您基本上将问题简化为O(n/8)通过使用预先计算的查找表

您可以构建更大的查找表以获得更快的速度,但这将占用更多内存


虽然我无法想象n=100的O(n)算法会对您造成性能问题。除非您在某个内部循环中经常调用它?

我假设列表在您搜索时不会更改,但它会一直更改,直到您决定搜索,然后您再执行您的操作

每个字节有2^8=256个0和1的组合。这里有100/8=13个字节要检查

因此,您可以构建一个包含256个条目的查找表。键是您正在位流中检查的字节的当前实际值,值是您查找的数据(一个包含1位位置的元组)。因此,如果给它5,它将返回{0,2}。此查找的成本是恒定的,内存使用量非常小

现在,当您遍历位流时,您可以一次处理一个字节的数据(而不是一次处理一个字节),只需跟踪当前字节数(当然从0开始),并将8*当前字节数添加到返回的元组中的值中。因此,现在您基本上将问题简化为O(n/8)通过使用预先计算的查找表

您可以构建更大的查找表以获得更快的速度,但这将占用更多内存


尽管我无法想象n=100的O(n)算法确实会给您带来一些性能问题。除非您在某个内部循环中经常调用它?

正如其他人所说,在没有进一步结构的情况下查找n个最低设置位是O(n)操作

如果您希望提高性能,您是否考虑过问题的实现方面

在我的头顶上,q&~(q-1)将只保留数字q中设置的最低位,因为从任何二进制数中减去1将填充从右边到设置的第一个数字的1s,将该数字更改为0,并保留其余数字。在设置了1位的数字中,向右移位并对零进行测试,可提供一个简单的测试,以区分是否存在潜在答案小于真实答案或大于或等于。因此,您可以从那里进行二进制搜索

要找到下一个,请删除最低的数字,并使用较小的初始二进制搜索窗口。可能有更好的解决方案,但这应该比从最小到最大检查每一位并检查是否已设置好要好

这种实现方式不会影响复杂性,但可能有助于提高性能。

与其他实现方式一样