考虑由整数A = [a1,a2,a3 ... an]组成的数组n。查找并打印对的总数,以使ai * aj <= max(ai,ai + 1,..... aj)其中i <j

时间:2018-10-09 13:11:14

标签: python algorithm data-structures

有人可以帮助我解决上述问题。 我们必须在数组(a1,a2),(a1,a3),(a1,a4)....中找到元素的组合,然后选择满足条件(ai * aj)<= max的那些组合(A),其中A是数组,并返回可能的组合数。

示例:输入数组A = [1,1,2,4,2],由于组合为:它返回8: (1,1),(1,2,2,(1,4),(1,2),(1,2),(1,4),(1,2),(2,2)。

使用嵌套的for循环很容易解决这个问题,但这非常耗时。(O(n ^ 2))。

天真算法:

array = [1,1,2,4,2]
result = []
for i in range(len(array)):
   for j in range(len(array)):
       if array[i] * array[j] <= max(array):
           if (array[j],array[i]) not in result:
               result.append((array[i],array[j]))
print(len(result))

遇到此类问题该怎么办?

3 个答案:

答案 0 :(得分:0)

如何对数组进行排序然后进行迭代:对于每个元素e,二进制搜索与floor(max(A) / e)最接近的元素,该元素小于或等于e。在该索引的左侧添加元素数量。 (如果有很多重复项,则对它们的哈希进行哈希处理,在已排序的数组中仅显示其中两个,并使用前缀总和将正确数量的项目返回到任何索引的左侧。)

1 1 2 4 2

1 1 2 2 4
0
  1
    2
      3
        2

答案 1 :(得分:0)

  

使用嵌套的for循环很容易解决这个问题,但这非常耗时。(O(n ^ 2))。

where i < j起,我们可以减少一半:

for i in range(len(array)):
  for j in range(i+1, len(array)):
    ...

现在让我们摆脱if (array[j],array[i]) not in result:这部分内容,因为它不能反映出您的结果:(1,1),(1,2),(1,4),(1,2),(1,2),(1,4),(1,2),(2,2)在这里您有骗子。

我们可以摆脱的下一个昂贵的步骤是max(array),这不仅是错误的max(ai,ai+1,…aj)转换为max(array[i:j]),而且还必须迭代一个每次迭代中数组的整个部分。由于数组不变,因此唯一可以更改此最大值的就是array[j],即您正在处理的新值。

让我们将其存储在变量中:

array = [1,1,2,4,2]
result = []

for i in range(len(array)):
  maxValue = array[i]
  for j in range(i+1, len(array)):
    if array[j] > maxValue:
      maxValue = array[j]
    if array[i] * array[j] <= maxValue:
      result.append((array[i], array[j]))

print(len(result))

仍然是一种幼稚的算法,但是imo我们已经进行了一些改进。

我们可以做的另一件事是不仅存储maxValue,而且存储pivot = maxValue / array[i],因此用简单的比较if array[j] <= pivot:代替乘法。在这样的假设下,乘法将比maxValue被更频繁地调用,因此pivot会发生变化。

但是由于我对python不太熟悉,所以我不确定这是否会对python有所帮助,或者我是否正在为此进行无用的微优化。

答案 2 :(得分:0)

根据您对问题的描述,我了解到的是,您要查找对的总数小于其对范围内的最大元素的对,即ai*aj <= max(ai,ai+1,…aj)

replaceFileInput建议的幼稚方法很容易理解,但仍具有O(n^2))的时间复杂性。我们可以对此进行优化,以将时间复杂度降低到O(n*log^2n)。让我们详细讨论一下。

首先,我们从每个索引i中找出{l, r}的范围,其中索引i上的元素将大于或等于从l到{{ 1}},并且大于所有从ii + 1的元素。使用Thomas的想法可以很容易地以O(n)时间复杂度来计算。

现在,让我们为每个索引i找出这样一个范围r,如果我们想遍历{l, r}两个范围之外的最小长度,那么总体上我们将遍历{{1 }}整体数组的索引。当遍历较小的长度范围时,如果遇到某个元素说min( i - l, r - i ),则我们必须以某种方式找出其他范围内存在多少个元素,使得值小于n*logn。对于每个查询,可以使用O {logn)时间复杂度为histogram data-structure的脱机处理来解决此问题。因此,我们可以用x时间复杂度的整体复杂度来解决上述问题。