这是悦乐书的第275次更新,第291篇原创

01 看题和准备

今天介绍的是LeetCode算法题中Easy级别的第143题(顺位题号是628)。给定一个整数数组,从其中找出三个数,使得乘积最大。例如:

输入:[1,2,3]

输出:6

输入:[1,2,3,4]

输出:24

注意

  • 数组的长度范围为[3,10^4],元素值范围为[-1000,1000]。

  • 任意三个数字的乘积不会超过32位有符号整数的范围。

本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

02 第一种解法

要想三个数的乘积最大化,那么他们的值在数组中肯定是最大的,所以我们需要排序。

元素的取值范围是[-1000,1000],会存在负数的值大于正数的值的情况。对数组排序后,第三个数肯定是数组最后一个元素,如果数组中存在负数,前两个负数的乘积大于倒数第二个元素与倒数第三个元素的乘积,那么第一个数与第二个数就是数组的前两位元素,反之就是数组的倒数第二个元素与倒数第三个元素,我们从这两种情况中取最大值即可。

此解法时间复杂度是O(nlog(n)),空间复杂度是O(1)。

public int maximumProduct(int[] nums) {
if (nums == null || nums.length < 3) {
return 0;
}
// 排序
Arrays.sort(nums);
// 取两种情况的较大者
return Math.max(nums[0]*nums[1]*nums[nums.length-1], nums[nums.length-1]*nums[nums.length-2]*nums[nums.length-3]);
}

03 第二种解法

对第一种解法中借助Arrays.sort方法来实现排序,我们可以再优化下,让排序时间复杂度降到O(n),使用记数排序算法来实现。记数排序算法在之前的一道题目里用过,可以稍后去看看文末的链接。

此解法的时间复杂度是O(n),空间复杂度是O(n),使用了新数组,n为新数组的长度。

public int maximumProduct2(int[] nums) {
if (nums == null || nums.length < 3) {
return 0;
}
// nums的取值范围是[-1000,1000],定义一个新数组的长度比它多一个即可
int[] temp = new int[2001];
for (int n : nums) {
// 以nums的元素值加1000作为新数组的索引,出现次数作为值
temp[n+1000]++;
}
int index = 0;
for (int i=0; i<temp.length; i++) {
// 遇到了nums的元素
if (temp[i] != 0) {
// 可能出现多次,temp[i]为nums中该元素出现的次数
for (int j=0; j<temp[i]; j++) {
nums[index++] = i-1000;
}
}
}
// 依旧取两者中较大的那个
return Math.max(nums[0]*nums[1]*nums[nums.length-1], nums[nums.length-1]*nums[nums.length-2]*nums[nums.length-3]);
}

04 第三种解法

是不是必须要排序才能找到乘积最大的三个元素?

我们可以换个场景,找一组数据中的最大值或者最小值,最简单的做法是直接遍历,依次比较就行,此题我们是不是也可以使用同样的思路?只不过原来是找一个最大值或最小值,现在变成要找三个最大值以及两个最小值了。

此解法的时间复杂度是O(n),空间复杂度是O(1)。

public int maximumProduct3(int[] nums) {
if (nums == null || nums.length < 3) {
return 0;
}
// 定义前三个最大值变量
int max1 = Integer.MIN_VALUE;
int max2 = Integer.MIN_VALUE;
int max3 = Integer.MIN_VALUE;
// 定义前两个最小值变量
int min1 = Integer.MAX_VALUE;
int min2 = Integer.MAX_VALUE;
for (int n : nums) {
// 做比较并进行替换,从后往前
if (n > max1) {
max3 = max2;
max2 = max1;
max1 = n;
} else if (n > max2) {
max3 = max2;
max2 = n;
} else if (n > max3) {
max3 = n;
}
if (n < min1) {
min2 = min1;
min1 = n;
} else if (n < min2) {
min2 = n;
}
}
// 同样是取两者之间的较大者
return Math.max(max1*max2*max3, min1*min2*max1);
}

05 小结

此题本质上是找数组中的最大值或最小值,无论是找单个还是多个,无论是使用排序算法还是其他方式,核心思路都不变。至于上面第二种解法中的记数排序算法,有个使用前提,就是得知道数组元素的取值范围,如果题目有给取值范围是最好的,没给的话,就需要自己去取了。

算法专题目前已日更超过四个月,算法题文章143+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,好看、留言、转发就是对我最大的回报和支持!

LeetCode算法题-Maximum Product of Three Numbers(Java实现)的更多相关文章

  1. LeetCode算法题-Maximum Average Subarray I(Java实现)

    这是悦乐书的第278次更新,第294篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第146题(顺位题号是643).给定由n个整数组成的数组,找到具有最大平均值的长度为k的 ...

  2. LeetCode算法题-Maximum Depth of N-ary Tree(Java实现)

    这是悦乐书的第261次更新,第274篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第128题(顺位题号是559).给定n-ary树,找到它的最大深度.最大深度是从根节点到 ...

  3. LeetCode算法题-Maximum Depth of Binary Tree

    这是悦乐书的第164次更新,第166篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第23题(顺位题号是104).给定二叉树,找到它的最大深度.最大深度是从根节点到最远叶节 ...

  4. 【算法】LeetCode算法题-Maximum Subarray

    这是悦乐书的第154次更新,第156篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第13题(顺位题号是53).给定一个整数数组nums,找出一个最大和,此和是由数组中索引 ...

  5. LeetCode算法题-Unique Morse Code Words(Java实现)

    这是悦乐书的第318次更新,第339篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第186题(顺位题号是804).国际莫尔斯电码定义了一种标准编码,其中每个字母映射到一系 ...

  6. LeetCode算法题-Robot Return to Origin(Java实现)

    这是悦乐书的第281次更新,第298篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第149题(顺位题号是657).在2D平面上有一个从位置(0,0)开始的机器人.给定其移 ...

  7. LeetCode算法题-Min Cost Climbing Stairs(Java实现)

    这是悦乐书的第307次更新,第327篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第176题(顺位题号是746).在楼梯上,第i步有一些非负成本成本[i]分配(0索引). ...

  8. LeetCode算法题-Longest Word in Dictionary(Java实现)

    这是悦乐书的第303次更新,第322篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第171题(顺位题号是720).给出表示英语词典的字符串单词数组,找到单词中长度最长的单 ...

  9. LeetCode算法题-1-bit and 2-bit Characters(Java实现)

    这是悦乐书的第302次更新,第321篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第170题(顺位题号是717).有两个特殊字符,第一个字符可以用一个比特0表示,第二个字 ...

随机推荐

  1. 【Spark篇】---Spark初始

    一.前述 Spark是基于内存的计算框架,性能要优于Mapreduce,可以实现hadoop生态圈中的多个组件,是一个非常优秀的大数据框架,是Apache的顶级项目.One stack  rule  ...

  2. java代码之美(4)---guava之Immutable(不可变)集合

    Immutable(不可变)集合 一.概述 guava是google的一个库,弥补了java语言的很多方面的不足,很多在java8中已有实现,暂时不展开.Collections是jdk提供的一个工具类 ...

  3. H5本地存储sessionStorage和localStorage的区别

    sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁.因此sessionStorage不是一种持久化的本地 ...

  4. 一纸理解JVM

    JVM,JDK,JRE定义 JVM是Java Virtual Machine(Java虚拟机)的缩写. JDK是Java Development Kit JAVA语言开发工具箱(JAVA核心) JRE ...

  5. CentOS安装Java JDK

    JDK是 Java 语言的软件开发工具包,主要用于移动设备.嵌入式设备上的java应用程序.在Linux上安装Tomcat,而Tomcat服务器运行时是需要JDK支持的,所以服务器必须配置好JDK用到 ...

  6. LeetCode专题-Python实现之第27题:Remove Element

    导航页-LeetCode专题-Python实现 相关代码已经上传到github:https://github.com/exploitht/leetcode-python 文中代码为了不动官网提供的初始 ...

  7. 设计模式总结篇系列:策略模式(Strategy)

    前面的博文中分别介绍了Java设计模式中的创建型模式和结构型模式.从本文开始,将分别介绍设计模式中的第三大类,行为型模式.首先我们了解下分为此三大类的依据. 创建型模式:主要侧重于对象的创建过程: 结 ...

  8. Spring Boot (十):邮件服务

    Spring Boot 仍然在狂速发展,才几个多月没有关注,现在看官网已经到 2.1.0.RELEASE 版本了.准备慢慢在写写 Spring Boot 相关的文章,本篇文章使用 Spring Boo ...

  9. windows查看端口占用 windows端口占用 查找端口占用程序 强制结束端口占用 查看某个端口被占用的解决方法 如何查看Windows下端口占用情况

    windows下查询端口占用情况 ,强制结束端口占用程序 查询8080端口被那个程序占用 如何强制结束windows下端口占用情况? 下面操作在win10下 在控制台执行命令   1.列出所有端口的情 ...

  10. 命令别名设置: alias, unalias

    别名命令:alias 命令别名是一个很有趣的东西,特别是你的惯用指令特别长的时候!还有, 增设默认的选项在一些惯用的指令上面,可以预防一些不小心误杀文件的情况发生的时候! 举个例子来说,如果你要查询隐 ...