leetcode 三个数的最大乘积

443 阅读2分钟

给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积。

示例 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 个数相乘中,两数中的最大值和最大的那个值相乘不一定是最大值,最后我只能使用这个算法了,但结果是超出时间范围。

这题我还想自己再想想,就不先看别人的做法了。

我仔细分析了各种情况:

  1. 如果数组全是正数/负数,那么乘积最大的肯定是排序后的最大的三个值;
  2. 如果包含0或一个负数,那么跟第一种情况相同;
  3. 如果有两个负数以上,但至少有一个正数,那么最大值有可能是最小两个数和最大值的乘积。

综上所述,乘积最大的那三个数只有两种情况,那么是最小两个数和最大数的乘积,要么就是全是最大数的乘积。

我的代码:

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)