在这种情况下,如何找到数组的最小索引?

时间:2019-03-04 04:19:31

标签: algorithm dynamic-programming

我们获得了一个包含n值的数组。

示例:[1,4,5,6,6]

对于数组i的每个索引a,我们构造一个数组b的新元素,

b[i]= [a[i]/1] + [a[i+1]/2] + [a[i+2]/3] + ⋯ + [a[n]/(n−i+1)],其中[.]表示最大的整数函数。

我们也给了整数k

我们必须找到最小值i,以使b[i] ≤ k

我知道蛮力O(n^2)算法(用于创建数组-'b'),有人可以建议更好的时间复杂度和解决方法吗?

例如,对于输入[1,2,3]k=3,输出为1(minimum-index)

a[1]=1; a[2]=2; a[3]=3;

现在,b[1] = [a[1]/1] + [a[2]/2] + [a[3]/3] = [1/1] + [2/2] + [3/3] = 3;

b[2] = [a[2]/1] + [a[3]/2] = [2/1] + [3/2] = 3;

b[3] = [a[3]/1] = [3/1] = 3 (obvious)

现在,我们必须找到索引i,以使b[i]<=kk='3'以及b[1]<=3,因此1是我们的答案! :-)

  

约束:-时间限制:-( 2秒),1 <= a [i] <= 10 ^ 5,1 <=   n <= 10 ^ 5,1 <= k <= 10 ^ 9

3 个答案:

答案 0 :(得分:4)

这是一种c_sub_category时间算法,用于计算c_sub_categories数组,其中$data = Tickets ::whereBetween('created_at', [$week["startDate"], $week["endDate"]]) ->where('status', 'closed') ->where('category', '!=', 'New Development') ->groupBy('c_sub_category') ->get(); whereBetween数组中的元素数,而$data = Tickets ->where('status', 'closed') ->where('category', '!=', 'New Development') ->groupBy('c_sub_category') ->get(); 是最大值$data = Tickets ::where(function ($query) use ($week) { $query->whereBetween('created_at', [$week["startDate"], $week["endDate"]]); }) ->where('category', '!=', 'New Development') ->where('status', 'closed') ->groupBy('c_sub_category') ->get(); $data = Tickets ::where(function ($query) use ($week) { $query->whereBetween('created_at', [$week["startDate"], $week["endDate"]]); }) ->where(function ($query) use ($week) { $query->where('category', '!=', 'New Development'); ->where('status', 'closed'); }) ->groupBy('c_sub_category') ->get(); 数组的元素。

此算法计算O(n √A)数组(b)的差分序列,并得出n本身作为累积和。由于差异是线性的,因此我们可以从a开始,在每个元素A上循环,然后在适当的位置添加a的差异序列。关键在于该差异序列是稀疏的(少于b个元素)。例如,对于∆b = b[0], b[1] - b[0], b[2] - b[1], ..., b[n-1] - b[n-2]

b

我们可以从子例程中得出差值序列,该子例程在给定正整数∆b = 0, 0, ..., 0的情况下,返回所有最大对的正整数a[i],使得对数[a[i]], [a[i]/2], [a[i]/3], ...

请参阅下面的完整Python代码。

2√a[i]

答案 1 :(得分:1)

这可能无法达到David Eisenstat的回答的效率,但是由于我花了很长时间弄清楚一个实现,所以我认为无论如何都要放弃它。实际上,它似乎是O(n^2)

b[i]的元素可能不规则,但其中的某些部分不是:

[a[1]/1] + [a[2]/2] + [a[3]/3]
           |------ s2_1 -----|
                      |-s1_1-|

           [a[2]/1] + [a[3]/2]
           |------ s2_2 -----|
                      |-s1_2-|

                      [a[3]/1]
                      |-s1_3-|


s2_1 < s2_2

s1_1 < s1_2 < s1_3

k上二元搜索s1s1_i大于k的任何结果都将排除一部分有序行(行为b_i s)。

在其余行的k上二元搜索s2s2_i大于k的任何结果都将排除一部分有序行(行为b_i s)。

这没有太大帮助,因为在最坏的情况下,我们的O(n ^ 2 * log n)复杂度大于O(n ^ 2)。

但是我们也可以水平搜索。如果我们知道b_i ≤ k,那么它将排除所有长度更大或相等的 行,并且排除了搜索较小的s(m)的需要,而不是因为较小的{{1} } s不能产生> = k的总和,但是因为它们必然会产生一个具有较高s(m)的和,因此我们正在寻找最小值i

JavaScript代码:

i

答案 2 :(得分:-1)

为什么计算b[i]会导致O(n²)?如果为i = 1,则需要执行n的步骤。如果为i = n,则需要一步来计算b [i] ...

Sum > k条件下中止总和时,可以改善计算。

Let a in N^n
Let k in N

for (i1 := 1; i1 <= n; i1++)
  b := 0
  for (i2 :=i1; i2 <= n; i2++)   // This loop is the calculation of b[i]
    b := b + ceil(a[i2]/(i2 + 1))
    if (b > k)
      break
  if (i2 == n)
    return i1