刷 leetcode三个数的最大乘积 | 刷题打卡
一、题目描述:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
提示:
3 <= nums.length <= 104 -1000 <= nums[i] <= 1000
示例 1: 输入:nums = [1,2,3] 输出:6
示例 2: 输入:nums = [1,2,3,4] 输出:24
示例 3: 输入:nums = [-1,-2,-3] 输出:-6
二、思路分析:
我的思路:
- 先从小到大排序
- 全是负数,肯定后三者乘积
- 没有负数,肯定后三者乘积
- 1个负数,还是后三者乘积
- 2个负数或者以上,要看看2个负数*最后一个的乘积和后三者的乘积哪个大
别人的思路1:
- 先从小到大排序
- 全是负数,后三者乘积
- 全是非负数,后三者乘积
- 有正有负,比较前两乘积和后三者的乘积谁大
简化了罗里吧嗦的判断,这里还巧用了
Math.max
别人的思路2:
- 其实这里需要最大的三个数和最小的两个数,所以不需要挨个排序
- 后面逻辑一样
哇哦,也是哦,不用挨个排序
三、AC 代码:
我的土鳖写法
const maximumProduct = function (nums) { const len = nums.length; if (len === 3) { return nums[len - 1] * nums[len - 2] * nums[len - 3]; } nums.sort((a, b) => a - b); console.log(nums); const lastBefore2 = nums[len - 2] * nums[len - 3]; const last3 = nums[len - 1] * lastBefore2; // 最小的都大于0,说明没有负数 const noHasLessThan0 = nums[0] >= 0; // 最小的小于0,第二小的大于0,说明只有一个负数 const hasOneLessThan0 = nums[0] < 0 && nums[1] >= 0; // 最大的小于0,说明全是负数 const allLessThan0 = nums[len - 1] < 0; if (noHasLessThan0 || hasOneLessThan0 || allLessThan0) { return last3; } const before2 = nums[0] * nums[1]; // const hasTwoLessThan0 = nums[0] < 0 && nums[1] < 0; return before2 < lastBefore2 ? last3 : before2 * nums[len - 1]; };
别人的全部排序写法:
const maximumProduct = function (nums) { const len = nums.length; nums.sort((a, b) => a - b); return Math.max( nums[len - 1] * nums[len - 2] * nums[len - 3], nums[len - 1] * nums[0] * nums[1]); };
别人的非全部排序写法:
var maximumProduct = function(nums) { // 最小的和第二小的 let min1 = Number.MAX_SAFE_INTEGER, min2 = Number.MAX_SAFE_INTEGER; // 最大的、第二大的和第三大的 let max1 = -Number.MAX_SAFE_INTEGER, max2 = -Number.MAX_SAFE_INTEGER, max3 = -Number.MAX_SAFE_INTEGER; for (const x of 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); };
四、总结:
- 在复杂度不增加的情况下,简化代码,让其更易读
- 排序不一定挨个排序,简化思路
- 怎么找到最小的两个数
- 巧用Math.max