题目描述:
给定一个无序数组,包含正数、负数和0,要求从中找出3个数的乘积,使得乘积最大,要求时间复杂度:O(n),空间复杂度:O(1)
输入描述:
数组里元素的个数n
无序整数数组A[n]
输出描述:
满足条件的最大乘积
示例1
输入
4
3 4 1 2
输出
24
一:分析
1.数组的输入
因为输入的第一行告诉了我们数组的大小,故我们可以构建动态数组来接收输入。
2.数据的类型
在OJ上给出的测试案例中,有一次的输出为807120253114,是一个12位整数,不论是int,float还是long型都存不下如此大的值:
int 2字节,65536;
long 4字节,2^31-1,(2,147,483,647),约21亿;
unsigned long 4字节,2^32-1,约42亿;
long long 8字节,2^63-1,(9,223,372,036,854,775,807),约9e18;
PS: C++11中才正式引入long long,古老编译器很容易发生未知问题
比较后,我们选用long long这一超长整型来存值。
3.如何判断哪三个数的乘积最大
因为数组中既可以存正数,又可以存负数,故需分情况讨论。
- 如果都为负数或正数,则需求出最大的三位数的乘积即可;
- 若只有一个正数,则需求出最小的两个负数与其乘积即可;
- 若只有两个正数, 则同只有一个正数是一样的;
- 若有三个或三个以上的正数,则要比较最小的两个数与最大的数三者之间的乘积与最大的三个数的乘积的大小。
4.排序算法
我们如何找出最大的几个数与最小的几个数呢?这里我们选用选择排序算法(具体算法请自行学习,也可看下面的代码学习)。
除了以上几点,我们还需要定义两个数组分别存最大的4个数和最小的两个数,下面的代码中数组bmax[]是用来存最大的四个数的,bmin[]是用来存最小的两个数的。我们每进行一次选择排序,都会将最大的和最小的值传入相应的数组中,然后利用bmax[]数组判断正数的个数,根据第3点中的乘积最大的判断条件来进行输出。
代码如下:
#include <iostream>
using namespace std;
int main()
{
int i, j;
long long bmax[4] = { 0 }, cmin[2] = { 0 };
cin >> i;
long long z, v;
//long long为一个超长的整型,因为此题的输出很大,超过12位整数的都有,故需用到此种类型
long long* a = new long long[i];
long long* p = new long long[i];
for (j = 0; j < i; j++)
{
cin >> a[j];
p[j] = a[j];
}
for (int m = 0; m <= 3; m++) //选择排序算法开始
{
int max = m, min = m;
for (int n = m + 1; n < i; n++)
{
if (a[max] < a[n])
max = n;
if (p[min] > p[n])
min = n;
}
if (max != m)
{
int t;
t = a[max];
a[max] = a[m];
a[m] = t;
}
bmax[m] = a[m]; //传最大值进数组
if (min != m)
{
int t;
t = p[min];
p[min] = p[m];
p[m] = t;
}
if (m <= 1)
cmin[m] = p[m]; //传最小值进数组
}
if (bmax[0] < 0)
{
cout << bmax[0] * bmax[1] * bmax[2];
}
else if (bmax[1] < 0||bmax[2]<0)
{
cout << bmax[0] * cmin[0] * cmin[1];
}
else
{
z = bmax[0] * bmax[1] * bmax[2];
v = bmax[0] * cmin[0] * cmin[1];
if (z > v) cout << z;
else cout <<v;
}
return 0;
}
解题成功