我有以下问题。
给定N个数字,范围-100..100。
需要重新排列元素以获得最大的产品价值总和。 此任务中的乘积和定义为A1 * A2 + A2 * A3 ... AN-1 * AN
例如,给定数字10 20 50 40 30。
然后,我们可以按照以下方式重新排列它们: 从左边10,30,50,40,20有最大10×30 + 30×50 + 50×40 + 40×20 = 4600
这个想法是对序列进行排序,然后将最大数字放在新序列的中间,然后将下一个最大数字放在右边,然后放到左边,依此类推。 但是,关于负数,这是行不通的。
我尝试过以下算法:
1)排序初始序列 2)如上所述处理正数和零值 3)处理负数如何描述 4)从正序中找到最小数,它可以是左或右元素,并在此数字处理后的负序之前加上。
例如,给定序列:
1,-2,3,-4,5,-6,7,-8,9,10,11,12,13,14,15,-16
预计产品的最大总和为1342。
我的算法给出了下一个重新排列:
3,7,10,12,14,15,13,11,9,5,1,-4,-8,-16,-6,-2
产品总和为1340。
这似乎有效,但事实并非如此。
你能告诉我吗?
答案 0 :(得分:0)
你的方法很合理,但你必须将正数和负数分开。
对数组进行排序并将其拆分为左右部分,一个包含所有负数,另一个包含所有非负数。像往常一样重新排列它们,中间的最大(绝对)值和两侧交替放置的递减值,但要确保每个部分中的最小值位于相反的两端。
具体来说,绝对值最小的负数应该是左边部分的最后一个元素,而具有最小值的非负值应该是右边部分的第一个元素。
然后连接这两个部分并计算相邻产品的总和。
这是一个有效的例子:
arr = [2, 3, 5, -6, -2, -5]
arr.sort() = [-6, -5, -2, 2, 3, 5]
left, right = [-5, -6, -2], [2, 5, 3]
max_sum_of_product = -5*-6 + -6*-2 + -2*2 + 2*5 + 5*3 = 63
我没有正确的正式证据,但这种方法与输入数组的所有排列上的强力搜索结果相同:
def max_sum_of_products(arr):
from itertools import permutations
n = len(arr)
###### brute force method
max1 = max([sum([a[x-1]*a[x] for x in range(1,n)]) for a in permutations(arr)])
###### split method
lo, hi = [x for x in arr if x<0], [x for x in arr if x>=0]
lo.sort()
hi.sort()
lo_ordered, hi_ordered = [], []
t = (len(lo)%2 == 1)
for x in lo:
if t:
lo_ordered = lo_ordered + [x]
else:
lo_ordered = [x] + lo_ordered
t = not t
t = (len(hi)%2 == 0)
for x in hi[::-1]:
if t:
hi_ordered = hi_ordered + [x]
else:
hi_ordered = [x] + hi_ordered
t = not t
arr = lo_ordered + hi_ordered
max2 = sum([arr[x-1]*arr[x] for x in range(1,n)])
return (max1, max2)
def test():
from random import randint
for i in range(10):
a = []
for j in range(randint(4,9)):
a = a + [randint(-10,10)]
print a,
(max1,max2) = max_sum_of_products(a)
if max2!=max1:
print "bad result :-("
else:
print max1
test()
答案 1 :(得分:0)
我在java中编写了一个方法,它将数组作为输入,并返回产品对的最大总和作为输出。
首先我计算负部分,然后计算正部分,然后返回它们的计算总和。 在计算负面部分时,如果元素的数量是奇数,则需要避免剩余的元素(因为它可以乘以0并且无效),我们这样做,以便负增加将降低总和。 所有其他负面项目都需要成对相乘并加总。
然后进入第二个正面部分,当我们看到1时,如果元素的数量是奇数,我们需要添加它,否则只需乘以前进。
public static long sum(int arr[]) {
Arrays.sort(arr);
long ans = 0;
long ans1 = 0;
boolean flag = false;
boolean flag2 = false;
int[] arr1 = new int[arr.length];
int[] arr2 = new int[arr.length];
int i = 0;
while (arr[i] < 0) {
arr1[i] = arr[i];
i++;
}
if (arr[i] == 0) flag = true;
if (i % 2 == 0) { //even -6,-5,-3,-2,-1
for (int j = 0; j < i - 1; j += 2) {
ans = arr1[j] * arr1[j + 1];
}
} else {
if (flag) {
for (int j = 0; j < i - 2; j += 2) {
ans = arr1[j] * arr1[j + 1];
}
}
}
int j = 0;
while (i<arr.length) {
arr2[j] = arr[i];
i++;
j++;
}
if (arr2[j] == 1) flag2 = true;
if (i % 2 == 0) {
for (int k=i-1; k>0; k-=2) {
ans1 = arr2[k] * arr2[k-1];
}
if (flag2) ans1 = ans1 + 1;
} else {
for (int k=arr2.length-1; k>1; k-=2) {
ans1 = arr2[k] * arr2[k-1];
}
ans1 = ans1 + arr2[0];
}
return ans + ans1;
}