一、题目描述:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
提示:
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