给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积。
示例 1:
输入: [1,2,3]
输出: 6
示例 2:
输入: [1,2,3,4]
输出: 24
注意:
- 给定的整型数组长度范围是[3,104],数组中所有的元素范围是[-1000, 1000]。
- 输入的数组中任意三个数的乘积不会超出32位有符号整数的范围。
一定要注意以下几点,我都没考虑,导致今天晚上都失败了:
/**
* @param {number[]} nums
* @return {number}
*/
var maximumProduct = function (nums) {
let max;
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
for (let k = j + 1; k < nums.length; k++) {
const res = nums[i] * nums[j] * nums[k]
if (max === undefined || res > max) {
max = res;
m = i;
n = j;
}
}
}
}
return max;
};
// 要考虑负数的情况
// 要考虑 0 的情况
// 要考虑执行时间过长的问题
// 在 3 个数相乘中,两数中的最大值和最大的那个值相乘不一定是最大值,最后我只能使用这个算法了,但结果是超出时间范围。
这题我还想自己再想想,就不先看别人的做法了。
我仔细分析了各种情况:
- 如果数组全是正数/负数,那么乘积最大的肯定是排序后的最大的三个值;
- 如果包含0或一个负数,那么跟第一种情况相同;
- 如果有两个负数以上,但至少有一个正数,那么最大值有可能是最小两个数和最大值的乘积。
综上所述,乘积最大的那三个数只有两种情况,那么是最小两个数和最大数的乘积,要么就是全是最大数的乘积。
我的代码:
var maximumProduct = function (nums) {
// 先把数组排好序
const tempNums = nums.sort((num1, num2) => num2 - num1);
const len = nums.length;
// 分别计算出两种情况的乘积值
const a = tempNums[0] * tempNums[1] * tempNums[2];
const b = tempNums[len - 1] * tempNums[len - 2] * tempNums[0];
// 看谁大返回谁
return a > b ? a : b;
};
我们发现这个算法的时间复杂度取决于排序,但其实我们可以不排序,因为我们只是想知道最大的三个值和最小的两个值,这个就是做了无用功。到时候再补上算法实现。
/**
* @param {number[]} nums
* @return {number}
*/
var maximumProduct = function (nums) {
// 先装5个元素,可能会低于这个数,不过没关系都包含在这过程中
let arr = [];
for (let i = 0; (i < 5 && nums[i] !== undefined); i++) {
arr.push(nums[i]);
}
// 排序这5个元素,从大到小还是从小到大没有关系,记住,在循环的过程中注意即可
arr = arr.sort((a, b) => a - b);
// 然后从数组的剩下元素中逐步找到对应的值
for (let j = nums.length - 1; j >= 5; j--) {
let num = nums[j];
let flag = true;
// 先放最大值
for (let k = arr.length - 1; k >= 2; k--) {
if (arr[k] < num) {
let temp = arr[k];
arr[k] = num;
num = temp;
flag = false;
}
}
// 再放入最小值
for (let l = 0; l <= 1 && flag; l++) {
if (arr[l] > num) {
let temp = arr[l];
arr[l] = num;
num = temp;
}
}
}
const len = arr.length
const a = arr[0] * arr[1] * arr[len - 1];
const b = arr[len - 1] * arr[len - 2] * arr[len - 3];
return a > b ? a : b;
};
可以发现虽然这样实现了,可是代码量一下就多了很多。只不过这个的时间复杂度是: O(n) ,而前一个是 O(nlogn)。
官方讲解: 三个数的最大乘积
来源:力扣(LeetCode)