1464.LeetCode - 数组中两元素的最大乘积 Maximum Product of Two Elements in an Array
给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)*(nums[j]-1) 取得最大值。
请你计算并返回该式的最大值。
Given the array of integers nums, you will choose two different indices i and j of that array. Return the maximum value of (nums[i]-1)*(nums[j]-1).
链接:https://leetcode-cn.com/problems/maximum-product-of-two-elements-in-an-array/
解法目录
题目分析
很多刚接触刷题的同学可能会想到简单的暴力枚举方法,枚举出所有的可能情况再取最大值。但会这样会会有两层循环,时间复杂度为O(n^2) 。所以我们要选择一些取巧的方法,充分利用题目的有利条件
- 1.由于数组规定全部为正数 可以对数组排序 Arrays.sort(nums)。取最末尾的两个值就能得到最大的值。API快速排序的时间复杂度O(nlogn)
- 2.把求最大值的问题转换成,求最大值和次最大值的这两个子问题,这样我们最多只需遍历两次数组。就可以获得最大的answer。
- 3.还有没有只遍历一次数组就同时获取 最大值和次最大值呢。当然是有的。
一、time O(n) 枚举一遍数组
每次比较过程中,一定会产生最大值的。
我们维护两个 记录最大值和次最大值的索引变量 maxInddex, preMaxIndex;
如果maxIndex发生了替换,那么被替换的maxIndex就变成次最大值preMaxIndex
如果maxIndex没有变动(nums[maxIndex] > nums[i]),nums[i] 与 nums[preMaxIndex]中产生次最大值,那么preMaxIndex与每个元素比较取最大 (i != j)
此解法 O(n) 打败100%
需要注意的是 两个变量的初始值不能相同。maxIndex 一定要设置成数组的起始位置。
public static int maxProduct(int[] nums){
if(nums.length <= 2) return (nums[0]-1)*(nums[1]-1);
int maxIndex = 0;
// 在每次比较过程中,一定会产生最大值的。if maxIndex发生了替换,么就变成次最大值
int preMaxIndex = 1;
for (int i = 1; i < nums.length; i++) {
if (nums[maxIndex] < nums[i]) {
preMaxIndex = maxIndex;
maxIndex = i;
}else{
preMaxIndex = nums[preMaxIndex] > nums[i]? preMaxIndex:i;
}
}
return (nums[maxIndex]-1)*(nums[preMaxIndex]-1);
}
}
二、time O(n) 遍历两遍数组
O(n)
利用冒泡排序的思想,在每次遍历中,比较相邻位置的两个元素,把大的元素放到后面的位置
这样在遍历两次后,数组末尾的两个数一定是最大的
public static int maxProduct(int[] nums){
if(nums.length <= 2) return (nums[0]-1)*(nums[1]-1);
//获取最大值和次最大值的下标
int maxIndex = 0;
int secondIndex = 0;
//尝试不进行交换,交互需要耗时
for (int i = 0; i < nums.length; i++) {
maxIndex = nums[maxIndex] > nums[i] ? maxIndex:i;
}
//把最大放到末尾
int temp = nums[nums.length-1];
nums[nums.length-1] = nums[maxIndex];
nums[maxIndex] = temp;
for (int i = 0; i < nums.length-1; i++) {
secondIndex = nums[secondIndex] > nums[i]?secondIndex:i;
}
return (nums[nums.length-1]-1)*(nums[secondIndex]-1);
}
三、API 快速排序
O(nlogn)
public static int maxProduct(int[] nums){
Arrays.sort(nums);
return (nums[nums.length-1]-1)*(nums[nums.length-2]-1);
}