携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情
题目链接:1464. 数组中两元素的最大乘积
题目描述
给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)*(nums[j]-1) 取得最大值。
请你计算并返回该式的最大值。
提示:
示例 1:
输入:nums = [3,4,5,2]
输出:12
解释:如果选择下标 i=1 和 j=2(下标从 0 开始),则可以获得最大值,(nums[1]-1)*(nums[2]-1) = (4-1)*(5-1) = 3*4 = 12 。
示例 2:
输入:nums = [1,5,4,5]
输出:16
解释:选择下标 i=1 和 j=3(下标从 0 开始),则可以获得最大值 (5-1)*(5-1) = 16 。
示例 3:
输入: nums = [3,7]
输出: 12
整理题意
题目给定一个整数数组 nums,让我们找到数组中下标不同的两个元素,使得两个数都 -1 后乘积最大。
解题思路分析
题目要求从数组中选取两个元素自减一后乘积最大,那么我们可以贪心的寻找数组中最大的元素和次大的元素,然后按照题意进行模拟即可。
具体实现
排序
- 首先对原数组
nums进行排序; - 选取数组中最大值和次大值,分别进行自减一后相乘即可。
遍历
排序的时间复杂度为 ,我们可以采取一次遍历的方法,维护最大值和次大值即可将时间复杂度降低为 ,节省排序所需的时间复杂度。
- 声明两个遍历
m1和m2分别表示最大值和次大值; - 因为题目数据范围提示数组元素的值最小值为
1,那么我们初始化m1和m2为0; - 然后遍历数组:
- 如果当前元素大于
m1时:我们首先将m1的值赋值给m2,然后更新m1的值为当前元素值; - 如果当前元素在不大于
m1的情况下,大于m2时:我们更新m2的值为当前元素值即可。
- 如果当前元素大于
- 最后输出
(m1 - 1) * (m2 - 1)即可。
复杂度分析
- 时间复杂度:排序方法的时间复杂度为 ,其中 为数组 的长度,主要为数组排序的时间复杂度。一次遍历,维护最大值和次大值的时间复杂度为 ,其中 为数组 的长度,需要遍历一遍数组。
- 空间复杂度:,仅使用常量空间。
代码实现
排序
class Solution {
public:
int maxProduct(vector<int>& nums) {
// 排序,从大到小
sort(nums.begin(), nums.end(), greater<int>());
return (nums[0] - 1) * (nums[1] - 1);
}
};
一次遍历,维护最大值和次大值
class Solution {
public:
int maxProduct(vector<int>& nums) {
// 找到数组中最大和次大的整数
int m1 = 0, m2 = 0;
for(int &num : nums){
if(m1 < num){
m2 = m1;
m1 = num;
}
else if(m2 < num) m2 = num;
}
return (m1 - 1) * (m2 - 1);
}
};
总结
- 该题的核心在于找到数组中的最大值和次大值,最直接的寻找方法为排序,其次难点在于考虑采用一次遍历的方法维护最大值和次大值。
- 在使用一次遍历的方法维护最大值和次大值的时候需要注意在更新最大值的时候需要先将最大值赋值给次大值。
- 测试结果:
结束语
人生的意义,如果仅在于追求成功,得到的快乐或许并不会多。真正带给你成就感的是成长。克服自身的弱点,探寻未知的领域,在这种不断打磨塑造自己的过程中,更能体会到由衷的喜悦和人生的价值。新的一天,加油!