Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 最大化由一个值限定的排序数组和中的因子数_Algorithm_Sorting - Fatal编程技术网

Algorithm 最大化由一个值限定的排序数组和中的因子数

Algorithm 最大化由一个值限定的排序数组和中的因子数,algorithm,sorting,Algorithm,Sorting,我有一个大小为n的整数排序数组。这些值不是唯一的。我需要做的是 :给定a B,我需要在O(n)中找到一个Ia解:从末尾开始计算a[n]-a[n-1]: 设d=14-12=>d=2和r=B-d=>r=5, 然后重复该操作,但将d乘以2: d=12-10=>d=2和r=r-2*d=>r=1, r=1算法结束,因为总和必须小于B: 使用索引为0..n-1的数组 i=1 r=B while(r>0 && n-i>1) { d=a[n-i]-a[n-i-1]; r-=i

我有一个大小为n的整数排序数组。这些值不是唯一的。我需要做的是 :给定a B,我需要在O(n)中找到一个
Ia解:从末尾开始计算a[n]-a[n-1]:
设d=14-12=>d=2和r=B-d=>r=5,
然后重复该操作,但将d乘以2:
d=12-10=>d=2和r=r-2*d=>r=1,
r=1算法结束,因为总和必须小于B:

使用索引为0..n-1的数组

i=1
r=B
while(r>0 && n-i>1) {
  d=a[n-i]-a[n-i-1];
  r-=i*d;
  i++;
}
return a[n-i+1];
也许一幅画能更好地解释

14       x
13       x  -> 2
12      xx
11      xx  -> 2*2
10    xxxx    -> 3*0
 9    xxxx   
 8    xxxx
 7    xxxx
 6    xxxx
 5    xxxx
 4   xxxxx
 3   xxxxx
 2  xxxxxx
 1 xxxxxxx
我认为你可以使用以下三个技巧在O(n)中完成:

累计金额 预计算存储和(A[0:k])的数组C[k]。
这可以通过时间O(n)中的C[k]=C[k-1]+A[k]递归地完成。 这个数组的好处是,您可以通过C[b]-C[A-1]计算sum(A[A:b])

最佳中点 因为元素是经过排序的,所以很容易计算出最佳i以最小化绝对值之和。事实上,最好的我总是在中间的条目中给出。 如果列表的长度为偶数,则两个中心元素之间的所有i值将始终给出最小绝对值

e、 g.对于列表10、10、12、14,中心元素为10和12,因此,i在10和12之间的任何值都将最小化总和

迭代搜索 现在,您可以对元素进行一次扫描,以找到最佳值

1. Init s=0,e=0
2. if the score for A[s:e] is less than B increase e by 1
3. else increase s by 1
4. if e<n return to step 2
我们可以使用预计算的数组C[k]计算这个表达式中的和

编辑 如果端点必须始终为n,则可以使用以下替代算法:

1. Init s=0,e=n
2. while the score for A[s:e] is greater than B, increase s by 1
def fast(A,B):
    C=[]
    t=0
    for a in A:
        t+=a
        C.append(t)

    def fastsum(s,e):
        if s==0:
            return C[e]
        else:
            return C[e]-C[s-1]

    def fastscore(s,e):
        m=(s+e)//2
        return (m-s+1)*A[m]-fastsum(s,m)+fastsum(m+1,e)-(e-m)*A[m]

    s=0
    e=0
    best=-1
    while e<len(A):
        if fastscore(s,e)<B:
            best=max(best,e-s+1)
            e+=1
        elif s==e:
            e+=1
        else:
            s+=1
    return best

print fast([1,2,10,10,12,14],7)
# this returns 4, as the 4 elements 10,10,12,14 can be chosen
PYTHON代码 下面是该算法的python实现:

1. Init s=0,e=n
2. while the score for A[s:e] is greater than B, increase s by 1
def fast(A,B):
    C=[]
    t=0
    for a in A:
        t+=a
        C.append(t)

    def fastsum(s,e):
        if s==0:
            return C[e]
        else:
            return C[e]-C[s-1]

    def fastscore(s,e):
        m=(s+e)//2
        return (m-s+1)*A[m]-fastsum(s,m)+fastsum(m+1,e)-(e-m)*A[m]

    s=0
    e=0
    best=-1
    while e<len(A):
        if fastscore(s,e)<B:
            best=max(best,e-s+1)
            e+=1
        elif s==e:
            e+=1
        else:
            s+=1
    return best

print fast([1,2,10,10,12,14],7)
# this returns 4, as the 4 elements 10,10,12,14 can be chosen
def fast(A、B):
C=[]
t=0
对于a中的a:
t+=a
C.附加(t)
def fastsum(s、e):
如果s==0:
返回C[e]
其他:
返回C[e]-C[s-1]
def快速评分(s、e):
m=(s+e)//2
返回(m-s+1)*A[m]-快和(s,m)+快和(m+1,e)-(e-m)*A[m]
s=0
e=0
最佳=-1

当e使用数组大小为N的
O(N)方法时,可以这样尝试:

minpos = position of closest value to B in array (binary search, O(log(N))
min = array[minpos]

if (min >= B) EXIT, no solution

// now, we just add the smallest elements from the left or the right
// until we are greater than B

leftindex = minpos - 1
rightindex = minpos + 1

while we have a valid leftindex or valid rightindex:
    add = min(abs(array[leftindex (if valid)]-B), abs(array[rightindex (if valid)]-B))
    if (min + add >= B)
        break
    min += add
    decrease leftindex or increase rightindex according to the usage

min is now our sum, rightindex the requested i (leftindex the start)
(有些指标可能不正确,这只是想法,而不是实施)

我猜,小b的平均情况是
O(log(N))
。只有当我们可以使用整个阵列时,才会出现线性情况


我不确定,但也许这可以在
O(log(N)*k)中完成,数组大小为N,k
。我们必须以一种巧妙的方式使用bin搜索来在每次迭代中查找leftindex和rightdex,这样在每次迭代中可能的结果范围就会变小。这很容易做到,但我们必须注意重复,因为它们可能会破坏我们的bin搜索缩减。

您选择的数字必须是连续的吗?例如,是否可以选择
11014
?我不够精确。是的,它们必须是连续的如果你选择
12
,你可以做
1-12+2-12+10-12+10-12+12-12+14-12<7
。那么为什么最好的答案是4呢?总和可能也是正的吗?@IVlad我认为它是绝对值的总和,所以你的情况下的分数是| 1-12 |+| 2-12 |+。。。哪个是>7@PeterdeRivaz-哦,对了,我的错。我觉得这不对。d的作用是什么?为什么你用2乘以3?为什么您确定最后一个因素会包括在内?如果您还不了解问题,则此算法似乎不正确。请随意询问method d表示从数组的末尾到开头遍历数组时当前元素与上一个元素之间的差异,它与计数器相乘的原因是,每次添加一个元素时,总和都会受到元素数量的影响。我仍然不理解这一点。这似乎不正确。为什么从阵列的右边缘开始?想象一个如下的例子:11020和B=4。你的算法将只包含因子20,但最好的答案是包含因子1,1,1(例如,给我1的值),因为它包含3个因子,而你的值只有1。我认为这是正的部分,而不是绝对值。我不确定我是否完全理解你的算法。我现在正在再次阅读它。但是我认为你不明白目标是什么。目标是使A[j]参与求和的最大数量小于B,而不是最小化求和本身。在一个示例数组11 10 20 30 40 50 60 70和B=5中,您的算法将返回什么?1,1,1。它寻找e-s的最大值。e-s等于A[j]s参与从s到e之和的数量。所以我认为如果我理解正确的话,它确实会最大化A[j]的数量。