数组入门练习:三个数的最大乘积

NC106 三个数的最大乘积

给出一个长度为 n n n ( n ≥ 3 n \ge 3 n3) 的数组 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 minv0minv1
  • m a x v 0 ≥ m a x v 1 ≥ m a x v 2 maxv_0 \ge maxv_1 \ge maxv_2 maxv0maxv1maxv2

则答案即为:
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(maxv0maxv1maxv2,maxv0minv0minv1)

接下来的内容为寻找 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 arriminv0,则执行更新操作:
      • 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<arriminv1,则执行更新操作:
      • m i n 1 = a r r i min_1 = arr_i min1=arri
    • 其他情况无需更新 m i n v minv minv 数组。
  • 更新 m a x v maxv maxv 数组:
    • 如果 a r r i ≥ m a x v 0 arr_i \ge maxv_0 arrimaxv0,则执行更新操作
      • 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>arrimaxv1,则执行更新操作
      • 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>arrimaxv2,则执行更新操作
      • m a x v 2 = a r r i maxv_2 = arr_i maxv2=arri
    • 其他情形无需更新 m a x v maxv maxv 数组。

时间复杂度: 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]);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值