C ++在巨大的数组上执行计算

时间:2013-01-10 07:06:15

标签: c++ arrays

我被问到一个求职面试的问题,我不知道正确答案....

问题是:

如果您有一个介于1和100之间的10 000 000英寸的数组,请确定(有效地)这些总数中有多少对总计为150或更少。

我不知道如何在循环中没有循环的情况下这样做,但这不是很有效。

有人请给我一些指示吗?

3 个答案:

答案 0 :(得分:7)

一种方法是创建一个包含100个元素的较小数组。遍历10,000,000个元素并计算每个元素的数量。将计数器存储在100个元素数组中。

    // create an array counter of 101 elements and set every element to 0
    for (int i = 0; i < 10000000; i++) {
          counter[input[i]]++;
    }

然后从1到100做第二个循环j,其中,循环k从1到min(150-j,j)。如果k!= j,则加上counter [j] * counter [k]。如果k = j,则加(计数器[j] -1)*计数器[j]。

总和是你的结果。

您的总运行时间以10,000,000 + 100 * 100 = 10,010,000(实际上小于此值)为界限。

这比(10,000,000)^ 2快得多,即100,000,000,000,000。

当然,你必须在内存中放弃101个int空间。

完成后删除计数器。

另请注意(如下面的讨论中所指出的)这是假设订单很重要。如果顺序无关紧要,只需将结果除以2。

答案 1 :(得分:0)

首先,我会对数组进行排序。然后你开始一次遍历排序的数组。您在该单元格中获得单个值n并找到仍然允许的对应最低值(例如,对于15,它是135)。现在,您可以在数组中找到此值的索引,这是n的对数量。总结所有这些,你有(如果我的思想正常工作)计算每对两次,所以如果你将总和除以2,你有正确的数字。

解决方案应该是O(n log n)与普通的解决方案相比,即O(n ^ 2)

答案 2 :(得分:0)

这些问题总是需要混合数学洞察力和有效的编程。他们不想要蛮力。

First Insight

可以根据数字与其他群体的配对方式对数字进行分组。

将它们放入:

1 - 50 | 51 - 75 | 76 - 100
  A    |    B    |    C
  • 小组A可与任何内容配对。
  • 小组B可与AB以及possibly C
  • 配对
  • 小组C可以与Apossibly B配对,但不能与C
  • 配对

possibly是我们需要更多洞察力的地方。

Second Insight

对于B中的每个数字,我们需要检查其补数为150的数量。例如,使用62组中的B,我们希望从组{{1}知道多少个数字小于或等于C

对于88中的每个号码,我们将这些符号加起来,例如得分为76,77,78,......,88。这在数学上称为部分和。

在标准库中有一个产生partial_sum

的函数
C

对称意味着只需要为一个组完成此总和。

第三(更晚)见解

计算组vector<int> tallies(25); // this is room for the tallies from C vector<int> partial_sums(25); partial_sum(tallies.begin(), tallies.end(), partial_sums.begin()); A的总计也可以使用B来完成。因此,不是仅计算组partial_sum,而是必须以其他方式跟踪总计,只需将每个数字的总数存储在1到100之间,然后在整个事物上创建partial_sum。 C将给出小于或等于50的数字,partial_sums [75]小于或等于75,而partial_sums [100]应为1000万,即所有小于或等于的数字100。

最后,我们可以计算partial_sums[50]B的组合。我们想要将所有50和100,51和99,52和98等的总和的总数加在一起。我们可以通过迭代从50到75和partial_sums从100到75来完成这个。有一个标准库函数inner_product可以处理这个问题。

这对我来说似乎很线性。

C