我被问到一个求职面试的问题,我不知道正确答案....
问题是:
如果您有一个介于1和100之间的10 000 000英寸的数组,请确定(有效地)这些总数中有多少对总计为150或更少。
我不知道如何在循环中没有循环的情况下这样做,但这不是很有效。
有人请给我一些指示吗?
答案 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)
这些问题总是需要混合数学洞察力和有效的编程。他们不想要蛮力。
可以根据数字与其他群体的配对方式对数字进行分组。
将它们放入:
1 - 50 | 51 - 75 | 76 - 100
A | B | C
A
可与任何内容配对。B
可与A
和B
以及possibly
C
C
可以与A
和possibly
B
配对,但不能与C
possibly
是我们需要更多洞察力的地方。
对于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