Leetcode 题解 - 数学-其他(3):找出数组中的乘积最大的三个数

[LeetCode] Maximum Product of Three Numbers 三个数字的最大乘积

分几种情况

全正 :最大三个 相乘

全负 : 最小三个相乘

有正有负: 两个负一个正 或者三个正

这么一总结只有3种情况,然后比较大小

Given an integer array, find three numbers whose product is maximum and output the maximum product.

Example 1:

Input: [1,2,3]
Output: 6

 

Example 2:

Input: [1,2,3,4]
Output: 24

 

Note:

  1. The length of the given array will be in range [3,104] and all elements are in the range [-1000, 1000].
  2. Multiplication of any three numbers in the input won't exceed the range of 32-bit signed integer.

 

这道题博主刚开始看的时候,心想直接排序,然后最后三个数字相乘不就完了,心想不会这么Easy吧,果然被OJ无情打脸,没有考虑到负数和0的情况。这道题给了数组的范围,至少三个,那么如果是三个的话,就无所谓了,直接相乘返回即可,但是如果超过了3个,而且有负数存在的话,情况就可能不一样,我们来考虑几种情况,如果全是负数,三个负数相乘还是负数,为了让负数最大,那么其绝对值就该最小,而负数排序后绝对值小的都在末尾,所以是末尾三个数字相乘,这个跟全是正数的情况一样。那么重点在于前半段是负数,后半段是正数,那么最好的情况肯定是两个最小的负数相乘得到一个正数,然后跟一个最大的正数相乘,这样得到的肯定是最大的数,所以我们让前两个数相乘,再和数组的最后一个数字相乘,就可以得到这种情况下的最大的乘积。实际上我们并不用分情况讨论数组的正负,只要把这两种情况的乘积都算出来,比较二者取较大值,就能涵盖所有的情况,从而得到正确的结果,参见代码如下:

我跟博主想的也是一样的 首先去掉全为正 全为负的情况

剩下的就是正负都有, 正负都有的情况,去最大值就是正的最后三个值,或者负数的前两个值乘以整数的最大值,只有这两种情况,那么比较最大值即可。

class Solution {
    public int maximumProduct(int[] nums) {
        int i = nums.length;
        Arrays.sort(nums);
        if(nums[0] >= 0)
            return nums[i-1] * nums[i-2] * nums[i-3];
        if(nums[i-1] <= 0)
            return nums[0] * nums[1] * nums[2];
        return Math.max(nums[i-1] * nums[i-2] * nums[i-3], 
                       nums[i-1] * nums[0] * nums[1]);
        
    }
}

下面这种方法由网友hello_world00提供,找出3个最大的数 || 找出一个最大的和两个最小的,相乘对比也能得到结果,而且是O(n)的时间复杂度,参见代码如下:

class Solution {
public:
    int maximumProduct(vector<int>& nums) {
        int mx1 = INT_MIN, mx2 = INT_MIN, mx3 = INT_MIN;
        int mn1 = INT_MAX, mn2 = INT_MAX;
        for (int num : nums) {
            if (num > mx1) {
                mx3 = mx2; mx2 = mx1; mx1 = num;
            } else if (num > mx2) {
                mx3 = mx2; mx2 = num;
            } else if (num > mx3) {
                mx3 = num;
            }
            if (num < mn1) {
                mn2 = mn1; mn1 = num;
            } else if (num < mn2) {
                mn2 = num;
            }
        }
        return max(mx1 * mx2 * mx3, mx1 * mn1 * mn2);
    }
};

第二次

class Solution {
    public int maximumProduct(int[] nums) {
        int n = nums.length;
        Arrays.sort(nums);
        int res1 = nums[n-1] * nums[n -2] * nums[n-3];
        int res2 = nums[n-1] * nums[0] * nums[1];
        int res3= nums[0] * nums[1] * nums[2];
        return Math.max(res1, Math.max(res2, res3));   
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值