NC106 三个数的最大乘积
给出一个长度为 n n n ( n ≥ 3 n \ge 3 n≥3) 的数组 a r r arr arr,包含 n n n 个正数,负数,或 0。从中任选三个数,使得乘积最大。
比如,输入为 [ − 10 , − 10 , − 10 , 2 , 3 , 4 ] [-10, -10, -10, 2,3,4] [−10,−10,−10,2,3,4]。选取 [ − 10 , − 10 , 4 ] [-10, -10, 4] [−10,−10,4] 可获得最大乘积 400。
方法一
要使乘积最大,则无非以下几种选法:
- 当 a r r arr arr 中全为非负数时,选取三个最大的数。
- 当 a r r arr arr 中全为负数时,选取三个最大的数。
- 其他情况,选取「三个最大的数」,选取「一个最大的数和两个最小的数」。
总结一下:要从 a r r arr arr 中找到最大的三个数 m a x v 0 maxv_0 maxv0, m a x v 1 maxv_1 maxv1, m a x v 2 maxv_2 maxv2,以及最小的两个数 m i n v 0 minv_0 minv0, m i n v 1 minv_1 minv1。为实现方便,不妨设:
- m i n v 0 ≤ m i n v 1 minv_0 \le minv_1 minv0≤minv1
- m a x v 0 ≥ m a x v 1 ≥ m a x v 2 maxv_0 \ge maxv_1 \ge maxv_2 maxv0≥maxv1≥maxv2
则答案即为:
max
(
m
a
x
v
0
∗
m
a
x
v
1
∗
m
a
x
v
2
,
m
a
x
v
0
∗
m
i
n
v
0
∗
m
i
n
v
1
)
\max(maxv_0*maxv_1*maxv_2, maxv_0*minv_0*minv_1)
max(maxv0∗maxv1∗maxv2,maxv0∗minv0∗minv1)
接下来的内容为寻找 m a x v 0 maxv_0 maxv0, m a x v 1 maxv_1 maxv1, m a x v 2 maxv_2 maxv2 以及 m i n v 0 minv_0 minv0, m i n v 1 minv_1 minv1 的过程。先定义两个数组并进行初始化:
- 将保存最小值的数组全部初始化为
INT_MAX
- 将保存最大值的数组全部初始化为
INT_MAX
long long minv[2] = {INT_MAX};
long long maxv[3] = {INT_MIN, INT_MIN, INT_MIN};
接下来,从前向后遍历 a r r arr arr,并在遍历过程中更新 m i n v minv minv 及 m a x v maxv maxv 数组。对于每个 a r r i arr_i arri,更新过程如下:
- 更新
m
i
n
v
minv
minv 数组:
- 如果
a
r
r
i
≤
m
i
n
v
0
arr_i \le minv_0
arri≤minv0,则执行更新操作:
- m i n v 1 = m i n v 0 , m i n v 0 = a r r i minv_1 = minv_0, minv_0 = arr_i minv1=minv0,minv0=arri
- 如果
m
i
n
v
0
<
a
r
r
i
≤
m
i
n
v
1
minv_0 \lt arr_i \le minv_1
minv0<arri≤minv1,则执行更新操作:
- m i n 1 = a r r i min_1 = arr_i min1=arri
- 其他情况无需更新 m i n v minv minv 数组。
- 如果
a
r
r
i
≤
m
i
n
v
0
arr_i \le minv_0
arri≤minv0,则执行更新操作:
- 更新
m
a
x
v
maxv
maxv 数组:
- 如果
a
r
r
i
≥
m
a
x
v
0
arr_i \ge maxv_0
arri≥maxv0,则执行更新操作
- m a x v 2 = m a x v 1 , m a x v 1 = m a x v 0 , m a x v 0 = a r r i maxv_2 = maxv_1, maxv_1 = maxv_0, maxv_0 = arr_i maxv2=maxv1,maxv1=maxv0,maxv0=arri。
- 如果
m
a
x
v
0
>
a
r
r
i
≥
m
a
x
v
1
maxv_0 \gt arr_i \ge maxv_1
maxv0>arri≥maxv1,则执行更新操作
- m a x v 2 = m a x v 1 , m a x v 1 = a r r i maxv_2 = maxv_1, maxv_1 = arr_i maxv2=maxv1,maxv1=arri
- 如果
m
a
x
v
1
>
a
r
r
i
≥
m
a
x
v
2
maxv_1 \gt arr_i \ge maxv_2
maxv1>arri≥maxv2,则执行更新操作
- m a x v 2 = a r r i maxv_2 = arr_i maxv2=arri
- 其他情形无需更新 m a x v maxv maxv 数组。
- 如果
a
r
r
i
≥
m
a
x
v
0
arr_i \ge maxv_0
arri≥maxv0,则执行更新操作
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)
class Solution {
public:
/**
* 最大乘积
* @param A int整型一维数组
* @param ALen int A数组长度
* @return long长整型
*/
long long solve(int* A, int ALen) {
long long minv[2] = {INT_MAX};
long long maxv[3] = {INT_MIN, INT_MIN, INT_MIN};
for (int i = 0; i < ALen; i++) {
if (A[i] <= minv[0]) {
minv[1] = minv[0];
minv[0] = A[i];
} else if (A[i] <= minv[1]) {
minv[1] = A[i];
}
if (A[i] >= maxv[0]) {
maxv[2] = maxv[1];
maxv[1] = maxv[0];
maxv[0] = A[i];
} else if (A[i] >= maxv[1]) {
maxv[2] = maxv[1];
maxv[1] = A[i];
} else if (A[i] > maxv[2]) {
maxv[2] = A[i];
}
}
return max(maxv[0] * maxv[1] * maxv[2], maxv[0]*minv[0]*minv[1]);
}
};