C++ C++;在大型阵列上执行计算

C++ C++;在大型阵列上执行计算,c++,arrays,C++,Arrays,有人问我一个求职面试的问题,我不知道正确答案 问题是: 如果在1和100之间有10000个整数的数组,请(有效地)确定这些整数的多少对相加为150或更少 我不知道如何在没有循环的情况下做到这一点,但这不是很有效 有人能给我一些指针吗?一种方法是创建一个由100个元素组成的较小数组。循环遍历10000000个元素并计算每个元素的数量。将计数器存储在100元素数组中 // create an array counter of 101 elements and set every elemen

有人问我一个求职面试的问题,我不知道正确答案

问题是:

如果在1和100之间有10000个整数的数组,请(有效地)确定这些整数的多少对相加为150或更少

我不知道如何在没有循环的情况下做到这一点,但这不是很有效


有人能给我一些指针吗?

一种方法是创建一个由100个元素组成的较小数组。循环遍历10000000个元素并计算每个元素的数量。将计数器存储在100元素数组中

    // create an array counter of 101 elements and set every element to 0
    for (int i = 0; i < 10000000; i++) {
          counter[input[i]]++;
    }
//创建一个包含101个元素的数组计数器,并将每个元素设置为0
对于(int i=0;i<10000000;i++){
计数器[输入[i]]++;
}
然后在1到100之间进行第二个循环j。在这里面,有一个从1到min(150-j,j)的循环k。如果k=j、 添加计数器[j]*计数器[k]。如果k=j,则添加(计数器[j]-1)*计数器[j]

总数就是你的结果

总运行时间的上限是10000000+100*100=10010000(实际上比这个小)

这比(10000000)^2快得多,后者是1000000000000

当然,您必须在内存中放弃101 int空间

完成后删除计数器


还请注意(正如下面讨论中所指出的),这是假设顺序很重要。如果顺序不重要,只需将结果除以2。首先,我将对数组进行排序。然后开始对已排序数组进行一次遍历。得到该单元格中的单个值n,并找到仍然允许的对应最低值(例如,对于15,它是135)。现在在数组中找到这个值的索引,这就是n的对数。把所有这些加起来,你(如果我的思维正常的话)已经把每一对数了两次,所以如果你把总和除以2,你就得到了正确的数字


解决方案应该是O(n logn),而不是简单的O(n^2)

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

第一洞察 数字可以根据它们与其他组的配对方式进行分组

将它们放入:

1 - 50 | 51 - 75 | 76 - 100
  A    |    B    |    C
  • A
    可以与任何对象配对
  • B
    可以与
    A
    B
    配对,并且
    可能与
    C
  • C
    可以与
    A
    配对,可能与
    B
    配对,但不能与
    C
可能
是我们需要更多洞察力的地方

第二洞察 对于B中的每个数字,我们需要检查有多少个数字与其150的补数。例如,对于来自组
B的
62
,我们想从组
C
知道有多少个数字小于或等于
88

对于
C
中的每个数字,我们将计数相加,例如76、77、78、…、88的计数。这在数学上称为部分和

在标准库中,有一个函数可以生成


由于整数都在1到100之间,我们可以非常便宜地通过数组计算1的个数、2的个数等等。从那时起,我们只操纵100个数字,而不是10000000个。(假设“pairs”是指数组中的任意位置的pairs,否则就更容易了。)pairs表示它们必须相邻?基本上你想求5000000个整数对的和吗?我把对数表示为数组中的任意两个,而不是,比如说,任意数量的加数。这个问题是不完整的。它没有指定是否“使用”数字。如中所示,如果您使用一个数字将其与一个配对,那么您是否可以再次使用相同的数字将其与另一个配对?如果没有,您需要首先设计一个算法来确定有效配对!你的第一反应应该是“你说的一对是什么意思?”?如果这个问题故意含糊其辞,以了解您对含糊其辞的规范的反应,我不会感到惊讶。我可以想象OP会因为使用
new
编译时已知的100大小数组而受到批评。只是一点。另外,您必须从
输入[i]
中减去一个,或者使数组比必须的大一个。这一点很好。当然,new的一个优点是,如果该大小以后发生变化,那么炸毁堆栈就没有问题了。i、 如果写这段代码的人退出,一个新的程序员加入,需求改变,会发生什么?哦,是的,-1是个好球!如果你真的在意的话,我建议你使用一个向量,但是一个新手在将数组的大小更改为真正大的时候应该会自动提高警惕。这也可以奏效,但是它会带来开销,并且假设你有stl(或者一些带有向量的库)。这要视情况而定。底线是有一百万种方法可以做到这一点。如果你仔细考虑一下这个问题,也许有一种聪明的方法可以减少临时内存需求。好吧,
new
不需要太多内存
new()
将值初始化它。当然,下一个问题是:如何对1000万个整数进行排序?除了
135
超出范围之外,如何找到
135
的索引?线性搜索,二进制?STL排序和查找。O(logn)用于查找,O(logn)用于搜索。
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());
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> dis(1, 100);

vector<int> tallies(100);
for(int i=0; i < 10000000; ++i) {
    tallies[dis(gen)]++;
}

vector<int> partial_sums(100);
partial_sum(tallies.begin(), tallies.end(), partial_sums.begin());

int A = partial_sums[50];
int AB = partial_sums[75];
int ABC = partial_sums[100]; 
int B = AB - A;
int C = ABC - AB;

int A_match = A * ABC;
int B_match = B * B;
int C_match = inner_product(&tallies[50], &tallies[75],
                            partial_sums.rend(), 0);