Leetcode 628: Maximum Product of Three Numbers

问题描述:
Given an integer array nums, find three numbers whose product is maximum and return the maximum product.
给定任意数组,选三个值使其乘积最大

限定条件:
3 <= nums.length <= 10000 (保证至少三个数)
-1000 <= nums[i] <= 1000 (数值可正可负)

思路:
1:如果只有三个数,那么就返回这三个数的乘积,别无其它选择
2:如果有超过三个数,我们才需要制定策略,当然要先排序
(1)如果最大值都小于等于零,最优乘积就是最大三个数乘积
例如(-8,-6,-6,-3,-2,-2,-1,0)
(2)如果最小值都大于等于零,最优乘积就是最大三个数乘积
例如(0,2,3,4,5,8,8,9,9)
(3)其它:即超过三个数且正负数混合,我们通过一定策略可以保证乘积非负。无非以下两种情况求较大值:(最大三个)或(最小两个加最大一个)的较大值。原理如下:我们可以这样想,从排好序的数组左侧(即最小值一侧)选几个数可以使乘积为正?选0个,当然可以,如果最大值的绝对值够大;选1个,不会出现这种情况,因为若这个数为正,则它不够大,若这个数为负,它只贡献了一个负号;选2个,可以,如果这两个数的绝对值够大;选3个,不会出现这种情况,道理同上。

5月22日二刷心得:
其实不用像第一次想的这么复杂,因为有一点是能确定的,就是在排好序的数组中取值取两端的值,因为只有极值和极值的乘积会出现极值。根据输入数据的不同,我们要尽最大努力使乘积为正。选三个数,乘积为正,有可能是最大三个数的乘积(最大三个数最有可能都为正),或者是选最大数和最小两个数的乘积(最小两个数最有可能都为负,其乘积为正),其余情况不用考虑。

代码如下:

class Solution {
    public int maximumProduct(int[] nums) {
        int last = nums.length - 1;
        
        //case 0: when there are only 3 nums, then there is no choice
        if (last==2) return nums[last]*nums[last-1]*nums[last-2];
        
        //otherwise, we can sort the array to choose the best strategy
        Arrays.sort(nums);
        
        //case 1 and 2: when all nums are nonnegative or when all nums are nonpositive, product = product of largest 3
        if ((nums[last]<=0)||(nums[0]>=0)) return nums[last]*nums[last-1]*nums[last-2];
        
        //case 2: all others case(mix of negative and positive and >3 nums) we can guarantee a nonnegative product
        //there are two possible ways we grab numbers to get the maximum product:
        //(grab the largest 3) or (grab the smallest 2 and the largest 1), no other possibilities
        else{
            return Math.max(nums[last]*nums[last-1]*nums[last-2], nums[0]*nums[1]*nums[last]);
        }
    }
}

简化版代码如下:

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

时间复杂度:O(nlogn)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值