稀疏填充数组中的范围之间的总和小于O(n)?

时间:2016-02-21 08:21:47

标签: algorithm

假设有一个巨大的阵列,只填充了几个位置。我需要找到某个位置a和位置b之间的总和,a<湾

我能比O(n)做得更好吗?如果有,怎么样?

2 个答案:

答案 0 :(得分:0)

如果您的稀疏数组是作为一个天真的本机数组(例如int[999999])实现的,那么O(n/p)时间内没有比手动迭代更快的方式(其中p是你有硬件线程。)

如果您的稀疏数组以存储优化格式(例如页面数组或页面链接列表)存储,则最快的是O(m/p),其中m是pages和p是硬件线程的数量。

更新:

在评论中,您评论说您需要一个运行速度超过O(n)的单线程解决方案。这是不可能的。考虑这个稀疏数组:

arr = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 ]

计算机无法像人眼+大脑一样“一次”“看到”数组。单线程计算机一次只能处理一个字(通常为32或64位)的数据。所有计算机都知道arr内有一个数组,所以它开始读取它,它看到0,然后它再次读取0,依此类推,读取11 {{1}直到它最终遇到0值。这是1解决方案。

击败这个的唯一方法是使用并行化:人眼+大脑可以被认为是拥有超过5.76亿线程(人眼的90度has 576 megapixels)的机器,它“看到”我的StackOverflow中的整个数组立即发布(O(n))。对于计算机执行相同操作,您的程序必须具有许多线程(具有预编程的数据偏移),这些线程同时读取阵列,然后为您提供答案:

O(1)

这是获得void Main() { // Setup the threads volatile int total = 0; WaitHandle ev = new WaitHandle(); Int32[] arr; ev.Reset(); for(int i=0; i < 100; i++) { (new Thread( delegate() { int offset = i; ev.WaitOne(); total += arr[offset]; // assume this is a magic thread-safe increment operation } )).Start(); } // Load the array Int32[] arr = new Int32[] { /* 100 values */ }; ev.Set(); // unblock all 100 threads instantly // assume there's a magic Thread.Join() wait here Console.WriteLine("Total: {0}.", total); } 时间以数学方式计算稀疏数组之和的唯一方法。

...但即使这是不可能的,因为不存在“魔术线程安全添加”操作。您可以做的最好的是O(1) - 中间加法操作的级别(其中m的值为m),但它仍然非常接近Log[X](n)

答案 1 :(得分:0)