Arrays 将数组划分为K个部分

Arrays 将数组划分为K个部分,arrays,algorithm,Arrays,Algorithm,让数组 A[0] = 2 A[1] = 1 A[2] = 5 A[3] = 1 A[4] = 2 A[5] = 2 A[6] = 2 我必须把数组分成K个部分,这样更大的和是低的。 例如k=3 [2, 1, 5, 1, 2, 2, 2], [], [] with a large sum of 15; [2], [1, 5, 1, 2], [2, 2] with a large sum of 9; [2, 1, 5], [], [1, 2, 2, 2] with a l

让数组

 A[0] = 2
  A[1] = 1
  A[2] = 5
  A[3] = 1
  A[4] = 2
  A[5] = 2
  A[6] = 2
我必须把数组分成K个部分,这样更大的和是低的。
例如k=3

[2, 1, 5, 1, 2, 2, 2], [], [] with a large sum of 15;
[2], [1, 5, 1, 2], [2, 2] with a large sum of 9;
[2, 1, 5], [], [1, 2, 2, 2] with a large sum of 8;
[2, 1], [5, 1], [2, 2, 2] with a large sum of 6.
因此算法应该返回6。

我应该使用哪种算法,这是KMP算法的修改版本。
请提供一种方法。我相信您可以使用动态规划来实现这一点。这样想吧——如果你做一个切割,将前m个元素放入第一个块中,那么产生的最大值将是前m个元素之和的最小值,以及通过将最后n-m个元素切割成k-1块可以得到的最小值。作为基本情况,如果元素用完,则最小值为∞.

更正式地说,假设S[n,k]是在必须进行k次切割时,使用数组的前n个元素可以得到的最小最大值。您可以写出此循环:

S[0,k]=∞ 对于任意k(如果数组中没有元素,并且必须进行任意数量的剪切,则该值是无限的)

S[n,k]=minm≤ n{max(A[n]+A[n-1]+…+A[n-m],S[n-m,k-1]}对于n>0(从后面剥离一些元素,计算最小值作为最佳选择)

您需要填写一个包含Θ(nk)个总元素的表格,在位置(n',k')处填写元素需要花费时间Θ(n')。因此,总运行时间为Θ(n2k)

作为一种启发式方法,您可以将其加速一点。特别是,当a[n]+a[n-1]+…+a[m]大于S[n-m,k-1]时,您知道您在前面的组中剥离了太多的元素,因此可以停止评估更大的m值。这只是一个启发,但在实践中可能会给您带来一些性能优势

希望这有帮助!

templatetypedef的DP有一个
O(kn)
-时间优化,如下所示。当将第一个
j
元素划分为
i
部分时,让
p(i,j)
成为子阵列之间最后一个边界的最佳位置。然后
p(i,j)
i
中是不减损的

def minmaxsum(A,k):
S=[0]#部分和
对于A中的x:
附加(S[-1]+x)
n=len(A)
#V0是(i,j)子问题的最佳目标值
V0=[1e309]*(n+1)#1e309是无穷大
V0[0]=0
对于范围(k)内的j:
#V1是(i+1,j)子问题的最佳目标值
V1=[]
i0=0
对于范围(n+1)内的i1:
#while循环按固定时间摊销
而i0=\
最大值(V0[i0+1],S[i1]-S[i0+1]):
i0+=1
V1.追加(最大值(V0[i0],S[i1]-S[i0]))
V0=V1
返回V0[n]

为了进一步改进此解决方案,在充分“非冗余”输入上可能接近线性时间,我们观察到
sum(A)/k
是任何解决方案成本的下限。因此,对于
i
处的拆分,我们有下限
max(sum(A[:i])/(k-1),sum(A[i:])
。使用这个界限,我们可以使用二进制搜索找到最有可能的分割点,然后只计算少数DP条目,使用这个界限排除其余条目。

@user4018473你能详细说明一下吗?这个算法的时间复杂度很高,所以why@user4018473你能详细描述一下你遇到的问题吗ng?这是为了一个编程比赛,为了家庭作业,为了好玩吗?输入有多大?到目前为止你尝试了什么?我使用了分治(类似于最大子数组和)这只是为了提高我的算法技巧数组中有哪些元素?如果只有正数,它会大大简化问题。如果只有正的有限范围整数(如32位无符号整数),它进一步简化了问题。@EvgenyKluev只有一个正数。因此,在这种情况下,大卫的答案可能是你能得到的最好答案。
def minmaxsum(A, k):
    S = [0]  # partial sums
    for x in A:
        S.append(S[-1] + x)
    n = len(A)
    # V0 is the optimal objective values for the (i, j) subproblems
    V0 = [1e309] * (n + 1)  # 1e309 is infinity
    V0[0] = 0
    for j in range(k):
        # V1 is the optimal objective values for the (i + 1, j) subproblems
        V1 = []
        i0 = 0
        for i1 in range(n + 1):
            # the while loop is amortized constant-time
            while i0 < n and \
                    max(V0[i0], S[i1] - S[i0]) >= \
                        max(V0[i0 + 1], S[i1] - S[i0 + 1]):
                i0 += 1
            V1.append(max(V0[i0], S[i1] - S[i0]))
        V0 = V1
    return V0[n]