优化O(nlog(边界范围))时间中的列表中的最大值

时间:2018-10-09 23:44:35

标签: algorithm complexity-theory combinatorics greedy minimization

当前,我遇到一个问题,其中有两个数组,x=[x1,x2,x3,...,xn] 以及数组y=[y1,y2,y3,...,yn]和一个值k。现在,我必须从k生成一个说z=[z1,z2,z3,...,zn]的数组,这样z1+z2+z3...+zn=k。对于生成的不同z,[(x1-z1)*y1, (x2-z2)*y2, (x3-z3)*y3, ...., (xn-zn)*yn]的最大值的最小值将是什么。即最大值(x[i]-z[i])*y[i]的最小值。例如如果x=[2,3,4,1,6]y=[3,5,2,7,3]且k = 4,则取z=[0,1,0,0,3]得出的数组[6,10,8,7,9]的最大值为10,这也是最小值的最大值。
我设计了一种算法,可以在O(nlog(n)+k)中对其进行计算。如果k比我的算法大,那么效率会很低。我们可以在O(n)O(nlog(n))中做到吗? 我当前的算法是:

1. l=[] //initialize empty array
2. for i from 0 to n:
     l.append(x[i]*y[i],y[i])
3. Sort l in decreasing order of (x[i]*y[i])
4. while(m>0):
     num=l[0][0]-l[1][0] //take difference of two largest x[i]*y[i]
     t=(num/l[0][1])+1 //Choose appropriate number to subtract to minimize 
                         the maximum
     t=max(0,t)        // t must not be negative
     l[0][0]=l[0][0]-t*l[0][1]
     Put l[0] at correct position in sorted list l //Since value of 
                                                     l[0][0] has 
                                                     changed we will 
                                                     place it at 
                                                     correct position 
                                                     in already sorted  
                                                     l (using binary 
                                                     search)
     m=m-t
5.Print l[0][0] as the minimum maximum

1 个答案:

答案 0 :(得分:1)

如果您可以计算或估计答案的上下限(这是结果数组的最小可能最大值),则可以使用二进制搜索来解决此问题。

要二进制搜索答案,我们现在需要一个谓词,我们称它为p。

p(val) = true,如果存在数组z,使得(xi-zi) * yi的最大值小于等于val和{{1} }否则

要证明二进制搜索可以使用此谓词起作用,我们需要证明两件事:

  1. 如果false 然后p(a) = true代表所有p(b) = true
  2. 如果b >= a 然后p(a) = false代表所有p(b) = false

这两个语句可以使用谓词的定义来证明。

要评估给定值的谓词,请尝试估计每个b <= a

  1. 如果zi,则选择一个最小的xi * yi > val,使zi
  2. 否则,请选择最大可能的xi*yi - zi*yi <= val,以使zi仍然为真

现在,将出现三种情况:

  1. 如果xi*yi - zi*yi <= val的总和为zi,那么您可以选择任意一个正数<k并将其增加到zi的总和变为{{1} }。您可以看到,增大此zi不会影响谓词值,因为最大值k仍然小于zi。在这种情况下,谓词为真。
  2. 如果总和恰好为(xi-zi)*yi,则再次为true。
  3. 如果总和大于k,则结果为false。在这种情况下,无法选择负k并将其减少更多,因为它已经处于允许的最大值。

现在是时候编写一些代码了。

k

使用此方法,您可以在zi中计算结果