在问 · 算法题解

628. 三个数的最大乘积

简单数学一次遍历维护最值力扣原题 ↗

题目描述

输入一个整数数组 nums,其中可能有负数。

从数组中选出三个不同下标上的数相乘,返回所有选法中乘积的最大值。

示例 1
输入:nums = [1,2,3]
输出:6

解释:1 * 2 * 3 = 6。

示例 2
输入:nums = [1,2,3,4]
输出:24

解释:选 2、3、4,乘积为 24。

示例 3
输入:nums = [-1,-2,-3]
输出:-6

解释:只有三个数,乘积为 -6。

数据范围

  • 3 <= nums.length <= 10^4
  • -1000 <= nums[i] <= 1000

解题思路:一次遍历维护最值

最大乘积只可能来自两种组合:最大的三个数相乘;或者最小的两个数(两个负数,负负得正)乘最大的数。一次遍历同时维护最小的两个数 min1 ≤ min2 和最大的三个数 max1 ≥ max2 ≥ max3,最后取两种乘积的较大者。

为什么正确

遍历到第 k 个数时,min1、min2 是前 k 个数中最小的两个,max1、max2、max3 是最大的三个。

复杂度分析

时间 O(n),只遍历一次;空间 O(1)。

易错点

只取最大的三个数会漏掉“两个很小的负数乘最大正数”的情况;更新 max1 时要把旧的 max1、max2 依次下移,不能直接覆盖。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def maximumProduct(self, nums: List[int]) -> int:
        min1 = min2 = float('inf')
        max1 = max2 = max3 = float('-inf')
        for x in nums:
            if x < min1:
                min1, min2 = x, min1
            elif x < min2:
                min2 = x
            if x > max1:
                max1, max2, max3 = x, max1, max2
            elif x > max2:
                max2, max3 = x, max2
            elif x > max3:
                max3 = x
        return max(max1 * max2 * max3, min1 * min2 * max1)

载入编辑器,自己跑一遍 →

其他解法

两种解法的候选组合相同:最大三数之积或最小两数与最大数之积;排序法靠排序找到这五个数,一次遍历直接维护它们,省掉排序。

解法 2:排序 时间 O(n log n),空间 O(log n)

先把数组排序。最大乘积只可能来自两种组合:最大的三个数相乘;最小的两个数(可能都是负数)乘以最大的数。取两者较大值。

排序后五个候选数一目了然,代码极短。代价是 O(n log n) 的排序,并且会改动输入顺序。

class Solution:
    def maximumProduct(self, nums: List[int]) -> int:
        nums.sort()
        return max(nums[-1] * nums[-2] * nums[-3], nums[0] * nums[1] * nums[-1])

数学 专题的其他题目

查看 数学 全部题目 →