2个元素数组中的最大乘积
Posted
技术标签:
【中文标题】2个元素数组中的最大乘积【英文标题】:Max product in array of 2 elements 【发布时间】:2021-05-09 16:17:18 【问题描述】:给定一个正数数组,我需要找到表达式(j - i)*(b[j] + b[i])
的最大值,其中 j 和 i 是数组索引。我尝试使用分而治之,但在合并步骤中,我找不到一个有效的算法来组合左右子数组的结果。数组长度的约束为 1,000,000(最大数组大小),时间为 1 秒。感谢您的帮助
【问题讨论】:
能否请您提及来源,以便我可以在那里尝试一些想法? 数组中是否允许重复整数? 来自codeforces.com/gym/102920/problem/L 我试过你的方法但得到了TLE,也许你有更优化的实现 AMRO:TLE 不是 WA? Is your question answered? 【参考方案1】:让我们在这个问题上抛出两个指针:
left = 0, right = length of array - 1
do
max_product = max(max_product, (right-left)*(array[left]+array[right]))
if array[left] < array[right]:
left++
else
right--
while (left < right)
时间复杂度:O(数组大小),空间复杂度:O(1)
正如 Abinav 指出的那样,左边最大的贪婪选择是行不通的。因此,以下解决方案将不起作用。
这是一个基于动态规划的问题。维护一个dp
数组。 dp[index]
表示max(array[0]...array[index-1])
的索引。所以在每个index
你计算
result = max(result, (index - dp[index]) * (array[dp[index]]+array[index])).
时间复杂度:O(数组大小), 空间复杂度:O(数组大小)
尝试是否可以将空间减少到 O(1)
作为练习。
【讨论】:
为什么要贪婪地选择左边的最大值? @AbhinavMathur 对。贪婪的选择是行不通的。我会考虑更多。 @AbhinavMathur 现在怎么样? 你能证明这是最优的吗?[1,1000,1,1,1,1]
可能会失败
现在我们需要想一想对于相等的值要移动哪个指针?我们可以尝试一一选择,但时间复杂度会受到影响。如果允许重复,我认为我们需要了解问题的约束。【参考方案2】:
按照 Shridhar 的逻辑,我认为这应该可行。
const arr = [1,3,5,2,3,6,89,2,13,45,67,7,8,9]
let left = 0
let right = arr.length - 1
let max = (left - right) * (arr[left] + arr[right])
right--
let ref = 0
function algo(arr)
do
let sum = (left - right) * (arr[left] + arr[right])
if (sum > max) max = sum
ref++
if (ref % 2 === 0) right--
else left++
while(left < right)
return max
console.log(algo(arr))
【讨论】:
另一个答案中的算法不正确 这是正确的“如果数组[左] 你怎么确定?你测试/提交了吗? 把arr[]换成你喜欢的数字(negatif和positif),设置一个console.log(sum)和一个console.log(max),你会看到返回的数字总是最高的 除了这个错误,Shridhar 的逻辑和代码都不错【参考方案3】:扩展(j - i) * (b[j] + b[i])
,我们得到:
j*b_j + j*b_i - i*b_j - i*b_i
我们可以重写为常数和向量点积,
j*b_j + (j, -b_j, -1) ⋅ (b_i, i, i*b_i)
然后——假设j
th 之前的所有元素都已被看到——寻找:
j*b_j + max((j, -b_j, -1) ⋅ (b_i, i, i*b_i))
where i < j
使用凸包和最远点查询可以在对数时间内实现向量点积的最大化,尽管实现并非易事。
【讨论】:
以上是关于2个元素数组中的最大乘积的主要内容,如果未能解决你的问题,请参考以下文章