给定一个正整数数组,重新排列数组,以便最大化相邻元素的乘积之和

时间:2015-05-31 06:01:06

标签: arrays algorithm

面试问题。我正在寻找一种比O(n ^ 2)更好的算法,其中n是输入数组的大小。 (N< 5000)

问题陈述如下:

假设我们得到一个正整数数组(让我们称之为a)。找出一种方法来重新排列这些元素的顺序,以便可以最大化以下函数的值:

obj = a [0] * a [1] + a [1] * a [2] + ... + a [n-2] * a [n-1] + a [n- 1] * A [n]的

此外,还有一个布尔数组(让我们称之为b),它与正整数数组的大小完全相同。如果b [k] = false,则意味着当我们在正数组中重新排列元素时,我们无法移动第k个元素。

示例

a = [1,2,3],b = [true,true,true]

由于b的所有元素都是真的,我们可以根据我们所知道的重新排列数组。有六种方法可以重新排列它(例如[1,2,3],[1,3,2],[2,1,3] ....)。以下是这六种安排的目标函数值。最大化目标函数的安排是[1,3,2]或[2,3,1],因为:

1 * 3 + 3 * 2 = 9

2 * 3 + 3 * 1 = 9

另一个例子:

a = [1,2,3],b = [true,false,true]

在这种情况下,整数2不能移动,因此只有两个排列 - [1,2,3]和[3,2,1]。它们都产生相同的目标函数值。

更新

我使用强力方法测试@ shapiro.yaacov在具有不同元素的正整数数组上提供的算法。这是我运行的一些测试:

输入:[1,2,4,8,16,32,64]

输出:

obj = 3412,当[2,8,22,64,16,4,1]或

obj = 3412,当[1,4,16,64,32,8,2]

输入:[1,10,100,1000]

输出:

obj = 110100,当[1,100,1000,10]或

obj = 110100,当[10,1000,100,1]

正如您所看到的,至少有两种安排可以最大化目标函数 - 一种安排是另一种安排的反转版本。

即使这不是这个问题的要求,这个算法也适用于那些带0的数组。但是,我们需要在没有零的情况下提出最佳排列,然后将0添加到新排列的任一侧。例如:

输入:[0,1,2,4,8,16,32,64]

输出:

obj = 3412,当[2,8,32,64,16,4,1,0]或

obj = 3412,当[0,2,8,32,64,16,4,1]或

obj = 3412,当[1,4,16,64,32,8,2,0]或

obj = 3412,当[0,1,4,16,64,32,8,2]

1 个答案:

答案 0 :(得分:0)

这是$("#formId").on("submit", function(e){ e.preventDefault(); $.ajax({ method: "POST", url: "some.aspx", data: { name: "John", location: "Boston" } }).done(function(data) { if(data check) $("#formId").submit(); }); }); 的解决方案:

获取数组O(n*logn),并对其中的所有(可能)元素进行排序。可能我的意思是那些b数组中的索引是真的。此步骤需要a

<强>推荐使用:
给定 obj 函数,您希望将最大数字乘以第二大数字,将第二个数字与第三个数字相乘等。可以通过交换具有最小数字的O(n*logn)来完成某些优化,然后a [1]将是最大的等等(a[0] obj 更大)。在任何情况下,由于您已经对数组进行了排序,因此这一步很简单a = [1, 2, 3, 4, 8]

修改
鉴于 obj 功能,以及与@Edward Doolittle的对话后,这可能是最好的安排:

O(n)

编辑2:

处理无法移动的元素:首先排序可以排序的元素。然后查看它们可以去的位置,并通过两侧的乘数对位置进行排序。因此,如果一个可选位置一侧有8个而另一侧有3个,则乘数的值为24.然后将最高值元素分配给最高值位置。

现在无法证明这是最佳的,但它并非遥远。我想。