问题描述
给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积。
示例1:
输入:[1,2,3]
输出:6
示例2:
输入:[1,2,3,4]
输出:24
问题分析:
这是一道简单的力扣题,首先应该从数学角度分析,该数组没有告诉我们数组里面是正数还是负数,所以应该分别进行讨论。
方法一.排序
首先将数组排序。
如果数组中全是非负数,则排序后最大的三个数相乘即为最大乘积;如果全是非正数,则最大的三个数相乘同样也为最大乘积。
如果数组中有正数有负数,则最大乘积既可能是三个最大正数的乘积,也可能是两个最小负数(即绝对值最大)与最大正数的乘积。
综上,我们在给数组排序后,分别求出三个最大正数的乘积,以及两个最小负数与最大正数的乘积,二者之间的最大值即为所求答案。
class Solution {
public int maximumProduct(int[] nums) {
Arrays.sort(nums);
int n = nums.length;
return Math.max(nums[0] * nums[1] * nums[n - 1], nums[n - 3] * nums[n - 2] * nums[n - 1]);
}
}
复杂度分析:
时间复杂度:O(Nlog N),其中 N 为数组长度。排序需要 O(NlogN) 的时间。
空间复杂度:O(logN),主要为排序的空间开销。
方法二:线性扫描
在方法一中,我们实际上只要求出数组中最大的三个数以及最小的两个数,因此我们可以不用排序,用线性扫描直接得出这五个数。
class Solution {
public int maximumProduct(int[] nums) {
// 最小的和第二小的
int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
// 最大的、第二大的和第三大的
int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE;
for (int x : nums) {
if (x < min1) {
min2 = min1;
min1 = x;
} else if (x < min2) {
min2 = x;
}
if (x > max1) {
max3 = max2;
max2 = max1;
max1 = x;
} else if (x > max2) {
max3 = max2;
max2 = x;
} else if (x > max3) {
max3 = x;
}
}
return Math.max(min1 * min2 * max1, max1 * max2 * max3);
}
}
复杂度分析
时间复杂度:O(N),其中 N为数组长度。我们仅需遍历数组一次。
空间复杂度:O(1)。
个人总结:
这是一道简单的算法题,但不难总结出以下思路:
1.Java里常用的一个库函数是Arrays.sort()函数,使用该函数要注意时间空间复杂度,其中时间复杂度参考快速排序的O(NlogN),空间复杂度参考O(logN)。
2.算法思想很重要,该题主要思想是分类讨论然后找出需要的那五个数,所以认真读题以及别忽略边界条件很重要。
3.我觉得该题忽略了一个问题,即第一个为负数的时候这种情况该怎么讨论,然后仔细思考了一下,在解题最后用Math.max函数即可解决这种问题,此时返回的是最后三个值乘的和,然而在算法思想中却没有说明。

1658

被折叠的 条评论
为什么被折叠?



