leetcode-数组中两元素的最大乘积

给你一个整数数组 nums,请你选择数组的两个不同下标 ij,使 (nums[i]-1)*(nums[j]-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 。
输入:nums = [1,5,4,5]
输出:16
解释:选择下标 i=1 和 j=3(下标从 0 开始),则可以获得最大值 (5-1)*(5-1) = 16 。
输入:nums = [3,7]
输出:12

提示:

2 <= 1 nums.length <="500" code></=>

从描述中可以得出以下几个解题关键信息:

能否简单的使用双重循环暴力破解呢?不能,因为暴力破解会存在下标i=j的情况,假设nums[i]是数组中最大的值,那么就nums[i]=nums[j],这两个数相乘就成了最大的结果了。所以不能简单的使用双重循环。

题目的关键信息是i和j不同,那么在双重循环中去除掉i=j的情况不就行了?
举个栗子,i和j循环的所有值是i=1,2,3….;j=1,2,3….;进行双重循环的时候i=1,j从1开始到nums.length-1,将i=j的情况去掉就是在初始化时让j=i+1。同理当i=2时,j也不能小于2,因为当i=1的时候已经计算了[1,2]的结果。所以为了降低时间复杂度,不能再计算[2,1]的结果了。所以j>i即j=i+1。代码如下:

public int maxProduct(int[] nums) {
    //&#x65F6;&#x95F4;&#x590D;&#x6742;&#x5EA6;O(n^2)   &#x65F6;&#x95F4;&#x6362;&#x7A7A;&#x95F4;
    int max = 0;
    for(int i=0;i<nums.length;i++) { for(int j="i+1;j<nums.length;j++)" max="Math.max((nums[i]-1)*(nums[j]-1)," max); } return max; < code></nums.length;i++)>

既然是要取数组中两个不同的最大值,那么直接先进行排序然后取最前或者最后两个数不就行了?采用快速排序,平均时间复杂度为O(nlog2n)。代码就不列出了,网上很多实现。

能不能只进行一次遍历就解决呢?可以。
既然要保证取到最大的两个数,那么是不是可以给两个变量n1、n2,每次从nums数组中取一个数值替换n1、n2中更小的那个呢?这样nums数组只需要一次遍历,n1、n2也一直保证是当前遍历到的nums数组中最大的两个数。代码如下:

public int maxProduct(int[] nums) {
    //&#x65F6;&#x95F4;&#x590D;&#x6742;&#x5EA6;O(n),&#x6BCF;&#x6B21;&#x90FD;&#x5C06;&#x4E24;&#x4E2A;&#x6570;&#x91CC;&#x9762;&#x6700;&#x5C0F;&#x7684;&#x66FF;&#x6362;&#x6389;  &#x7A7A;&#x95F4;&#x6362;&#x65F6;&#x95F4;
    int n1=0,n2=0;
    for(int i=0;i<nums.length;i++) { if(n1<="n2)" n1="Math.max(nums[i]," n1); } else n2="Math.max(nums[i]," n2); return (n1-1)*(n2-1); < code></nums.length;i++)>

从这一道题想到了另外一题,如:给定一个数组,从中随机取3个数,共有多少种取法。
就是一个排列组合的问题,其实也是要去除重复的组合,可以采用暴力解法的优化方式去解,只是循环变成了三重。

Original: https://www.cnblogs.com/yywf/p/16626700.html
Author: 雨叶微枫
Title: leetcode-数组中两元素的最大乘积

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/587627/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球