algorithm - 如何随机读取整个数组中散布的所有 1's in an Array of 1' 和 0

标签 algorithm data-structures

我有一个数组,其中 1 和 0 随机分布在数组中。

int arr[N] = {1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,1....................N}

现在我想尽可能快地检索数组中所有的 1,但条件是我不应该丢失数组的确切位置(基于索引),因此排序选项无效。 所以剩下的唯一选择是线性搜索,即 O(n) ,还有比这更好的吗。

The main problem behind linear scan is , I need to run the scan even for X times. So I feel I need to have some kind of other datastructure which maintains this list once the first linear scan happens, so that I need not to run the linear scan again and again.

Let me be clear about final expectations-

我只需要在数组的某个范围内找到 1 的个数,准确地说我需要在数组中找到 40-100 范围内的 1 的个数。所以这可以是随机范围,我需要在该范围内找到 1 的计数。我不能做 sum 和 all,因为由于不同的范围要求,我需要一遍又一遍地遍历数组

最佳答案

我很惊讶您考虑将排序作为线性搜索的更快替代方法。

如果您不知道它们出现在哪里,那么没有比线性搜索更好的方法了。也许如果您使用位或 char 数据类型,您可以进行一些优化,但这取决于您要如何使用它。

您可以对此进行的最佳优化是克服分支预测。因为每个值都是零或一,所以您可以使用它来推进用于存储一索引的数组的索引。

简单的方法:

int end = 0;
int indices[N];

for( int i = 0; i < N; i++ )
{
    if( arr[i] ) indices[end++] = i;  // Slow due to branch prediction
}

没有分支:

int end = 0;
int indices[N];

for( int i = 0; i < N; i++ )
{
    indices[end] = i;
    end += arr[i];
}

[编辑] 我测试了上面的内容,发现没有分支的版本快了将近 3 倍(4.36 秒对 11.88 秒,在随机填充的 1 亿元素数组上重复 20 次)。

回来发布结果,我看到您已经更新了您的要求。使用动态编程方法,您想要的东西真的很容易...

您所要做的就是创建一个新的数组,它比数组大一个元素,它存储从数组开头到(但不包括)当前索引的 1 的数量。

arr   :   1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 1
count : 0 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 4 5 6 6 6 6 7

(我已经偏移了上面的arr所以它排列得更好)

现在您可以在 O(1) 时间内计算任意范围内 1 的数量。要计算索引 AB 之间的 1 的数量,您只需执行以下操作:

int num = count[B+1] - count[A];

显然,您仍然可以使用非分支预测版本来最初生成计数。相对于对每个查询求和的幼稚方法,所有这些都应该给你一个很好的加速:

int *count = new int[N+1];
int total = 0;

count[0] = 0;

for( int i = 0; i < N; i++ )
{
    total += arr[i];
    count[i+1] = total;
}


// to compute the ranged sum:
int range_sum( int *count, int a, int b )
{
    if( b < a ) return range_sum(b,a);
    return count[b+1] - count[a];
}

关于algorithm - 如何随机读取整个数组中散布的所有 1's in an Array of 1' 和 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16557144/

相关文章:

algorithm - 计算随机放在 table 上的卡片所覆盖的区域

java - 计算器算法 - 在二叉搜索树上使用迭代而不是递归

python - 给定一个字符串列表列表,找到最常见的字符串对,第二个最常见的对,.....,然后是最常见的字符串三元组,等等

c - 如何在c程序中扫描10^20或更大阶的数字?如何求大于 10^20 的数字平方的数字和?

javascript - 仅在尚未到位时添加

c++ - 建立索引 : Copies or pointers?

.net - 将对象列表绑定(bind)到网格而不是数据表有什么好处? (。网)

python - 解决数独的算法

algorithm - 最大化输入中不超过 k 个连续元素的列表总和

javascript - 获取数组中出现次数最多的项