由 8 个或更多位置分隔的数组中两个元素的最大乘积
Posted
技术标签:
【中文标题】由 8 个或更多位置分隔的数组中两个元素的最大乘积【英文标题】:Maximum product of two elements in an array separated by 8 or more positions 【发布时间】:2016-03-19 16:11:31 【问题描述】:这是我目前遇到的问题和代码。
我有一个正数序列。序列的长度大于 8,负数(不是序列的一部分)是序列结束的标志。我需要编写一个程序(按时间和内存使用量有效),找到由 8 个或更多位置分隔的 2 个元素的最大乘积。保证答案小于2000000000。
例如,对于1 2 3 4 5 6 7 8 9 10 -1
,答案将是20
。
我的代码:
#include <stdio.h>
#include <stdlib.h>
static long long int find_max(long int *v1, long int size)
const int d = 8;
long int arr[8];
long int maxi = 0;
long long int max_pr = 0;
for (int i = 1; i < d + 1; i++)
arr[i % d] = v1[i - 1];
for (int j = d + 1; j < size + 1; j++)
if (arr[j % d] > maxi)
maxi = arr[j % d];
if (v1[j - 1] * maxi > max_pr)
max_pr = v1[j - 1] * maxi;
arr[j % d] = v1[j - 1];
return max_pr;
int main()
long int seq[100000];
long int n = 0;
while (n < 100000 && scanf("%ld", &seq[n]) == 1)
if (seq[n] < 0)
break; //vector.push_back was too slow
n++;
long long int answer = find_max(seq, n);
printf("%lld ", answer);
return 0;
这是一门与我的学位无关的算法和数据结构公开课程的家庭作业。我的代码在测试系统上失败。我已经尝试解决这个问题几天了,但无法理解我在这里做错了什么,因为它对于我能想出的每个示例都运行良好。
非常感谢任何帮助。
【问题讨论】:
今后请保持理智的大括号风格。您的代码以前无法阅读。 另外,我们能得到一个提示吗?你能提供一个失败的测试用例吗?你的代码到底有什么问题? @ReousaAsteron 这是任务描述的一部分。仅用作序列结束的标志,因为它的长度是未知的。是的,去掉就好了 @Barry 我不知道出了什么问题,不幸的是,我没有任何测试用例示例。我将它发送到我的课程的在线测试系统,它只说它在测试 8 中失败并给出了错误的答案 您假设序列的长度最多为100000。为什么?正如 gnasher729 的回答所示,您不需要分配一个数组来存储整个序列。如果序列包含超过 100000 个元素,您的代码肯定会失败。 【参考方案1】:这很容易在线性时间内完成,不需要任何额外的存储空间。想想哪些数字可能是可能的解决方案:它可能是第一个数字乘以第九个数字。它可能是前两个中最大的一个,是第十个的倍数。它可能是前三个中最大的,乘以第十一个,依此类推。所以:
Set maxN = 0, maxProduct = 0, i = 0.
As long as v1 [i + 8] ≥ 0:
If v1 [i] > maxN then maxN = v1 [i]
If v1 [i + 8] * maxN > maxProduct then maxProduct = v1 [i + 8] * maxN.
Let i = i + 1.
就是这样。
【讨论】:
谢谢!我知道这是一项简单的任务,并且我从逻辑上理解它应该如何完成。我在这里发布的内容实际上并不是我尝试过的第一件事。您的解决方案在我的代码失败的同一测试中失败 @marinazz:如果您知道这是一项简单的任务,并且您从逻辑上理解它应该如何完成,那么您为什么做得这么糟糕?将所有元素读入数组是一件愚蠢的事情。 @TonyK 我的意思是我理解算法。我仍然不明白如果不将它们读入数组或向量中,我应该如何从输入中获取元素。我是一个绝对的初学者,即使我的整个问题都很愚蠢,也没有必要粗鲁。 @marinazzz:嗯,我很清楚 gnasher729 的算法只需要你存储最后 8 个值。【参考方案2】:您的算法没有按照问题要求您执行的操作。特别是,arr[8]
和 i%d
不是必需的。
以下是如何在 O(n) 时间内解决此问题,并且效率最高:
创建一个大小等于数组大小的数组maxSoFar
从左到右遍历数组seq
。将maxSoFar[i]
设置为seq
的最大值在i
的左侧
再次从索引8
开始遍历数组seq
,并找到seq[i] * maxSoFar[i-8]
中的max
。
这是一个随机序列的maxSoFar
示例:
seq: 1 4 3 5 2 12 8 6 14 19 7 9 25 20 13
maxSoFar: 1 4 4 5 5 12 12 12 14 19 19 19 25 25 25
第二遍应该产生这些值:
seq: 1 4 3 5 2 12 8 6 14 19 7 9 25 20 13
maxSoFar[i-8]: - - - - - - - - 1 4 4 5 5 12 12
mul: - - - - - - - - 14 76 28 45 125 240 156
因此,结果是 240。
注意:数组maxSoFar可以去掉。你能看出来吗?
【讨论】:
不错,但不如 gnasher729 的优雅解决方案高效,因为您需要额外的 O(n) 空间来实现相同的时间复杂度。 感谢您的回复!我已经尝试了这里发布的两种解决方案,但没有一个通过了我的程序失败的相同测试。 我现在认为问题可能出在函数的 main() 部分。以上是关于由 8 个或更多位置分隔的数组中两个元素的最大乘积的主要内容,如果未能解决你的问题,请参考以下文章
华为OD机试 - 计算最大乘积(Java) | 机试题+算法思路+考点+代码解析 2023
华为OD机试 - 计算最大乘积(Java) | 机试题+算法思路+考点+代码解析 2023
LeetCode 1460. 通过翻转子数组使两个数组相等 / 658. 找到 K 个最接近的元素 / 1464. 数组中两元素的最大乘积
LeetCode 1460. 通过翻转子数组使两个数组相等 / 658. 找到 K 个最接近的元素 / 1464. 数组中两元素的最大乘积