在数组中查找3个数字的最大乘积

时间:2013-12-12 17:22:48

标签: java arrays algorithm dynamic-programming

给定一个整数数组,它可以包含+ ve和-ve数字。我要最大化数组中任何3个元素的乘积。元素可以是不连续的。

一些例子:

int[] arr = {-5, -7, 4, 2, 1, 9};  // Max Product of 3 numbers = -5 * -7 * 9
int[] arr2 = {4, 5, -19, 3};       // Max Product of 3 numbers = 4 * 5 * 3

我尝试使用动态编程解决它,但我没有得到预期的结果。它在乘法中返回通常涉及相同数字两次的结果。因此,对于数组 - {4, 2, 1, 9},它返回 - 32,即4 * 4 * 2

这是我的代码:

public static int maxProduct(int[] arr, int count) {
    return maxProduct(arr, 0, arr.length - 1, count);
}

private static int maxProduct(int[] arr, int fromIndex, int toIndex, int count) {

    if (count == 1) {
        return maximum(arr, fromIndex, toIndex);
    } else if (toIndex - fromIndex + 1 < count) {
        return 1;
    } else {
        return MathUtil.max(maxProduct(arr, fromIndex, toIndex - 1, count - 1) * arr[toIndex - 1], 
                            maxProduct(arr, fromIndex, toIndex - 1, count));
    }
}
  • MathUtil.max(int a, int b)是一种最多提供ab的方法。
  • 我传递给max方法的两个值有:
    • maxProduct,当我们将最后一个元素视为产品的一部分时。
    • maxProduct,当我们不将其视为产品的一部分时。
  • count包含我们要考虑的元素数量。这里3
  • 对于count == 1,我们必须从数组中找到最多1个元素。这意味着,我们必须使用最大数组元素。
  • 如果toIndex - fromIndex + 1 < count,则表示数组之间的元素数量不足。

我有一种直觉,第一个if条件是失败的原因之一。因为,它只考虑来自阵列的最大元素,而最大乘积也可能包含负数。但我不知道该怎么处理。

我使用动态编程的原因是我可以将此解决方案概括为适用于count的任何值。当然,如果有人有更好的方法,即使对count = 3,我也欢迎这个建议(我希望避免对数组进行排序,因为这至少会是另一个O(nlogn)

22 个答案:

答案 0 :(得分:11)

按升序对给定数组进行排序,您必须采用这些情况的最大值 得到答案..

  1. 排序数组中最后3个数字的乘积
  2. 排序数组中前两个和最后一个数字的乘积

答案 1 :(得分:6)

对于count = 3,您的解决方案将包含3种形式之一:

  1. 3个最大正值(假设有3个正值)

  2. 最大正值和2个最小负值(假设有一个正值)

  3. 3个负面值

  4. 每个都可以比使用DP轻松解决。

答案 2 :(得分:2)

总是最大的(最小的两个负数和最大的正数或 最后三大正数)

public static void main(String args[]){

    int array[] = {-5,-1,4,2,1,9};
    Arrays.sort(array);

    int length = array.length;
    System.out.println(max(array[0]*array[1]*array[length-1], 
                           array[length-1]*array[length-2]*array[length-3]));   
}

答案 3 :(得分:1)

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ComputeMaxProduct {
    public static void main(String[] args){

        int [] arr = {4, 5, -19, 3};

        List<Integer> superSet = new ArrayList<>();

        for (int a : arr ){
        superSet.add(a);
        }

        int k = 3;

        int maxProduct = computeMaxProduct(superSet, k);
        System.out.println("maximum product is : " + maxProduct);
    }

    private static int computeMaxProduct( List<Integer> superSet, int k ){
        List<Set<Integer>> res = getSubsets(superSet,k);
        int maxProduct = 1;
        for(int index = 0; index < res.size(); index++){
        int product = 1;
        for(Integer i : res.get(index)){
            product *= i;
        }

        if (product > maxProduct){
            maxProduct = product;
        }
        }

    return maxProduct;
    }


    private static void getSubsets(List<Integer> superSet, int k, int idx, Set<Integer> current,List<Set<Integer>> solution) {
        //successful stop clause
        if (current.size() == k) {
            solution.add(new HashSet<>(current));
            return;
        }
        //unseccessful stop clause
        if (idx == superSet.size()) return;
        Integer x = superSet.get(idx);
        current.add(x);
        //"guess" x is in the subset
        getSubsets(superSet, k, idx+1, current, solution);
        current.remove(x);
        //"guess" x is not in the subset
        getSubsets(superSet, k, idx+1, current, solution);
    }

    public static List<Set<Integer>> getSubsets(List<Integer> superSet, int k) {
        List<Set<Integer>> res = new ArrayList<>();
        getSubsets(superSet, k, 0, new HashSet<Integer>(), res);
        return res;
    }
}

答案 4 :(得分:1)

public class MaxProdofThreenumbers {
public int ThreeLargeNumbers(int[] a) {
int topfirstpos = 0;
    int topsecpos = 0;
    int topthirdpos = 0;
    int topfirstneg = 0;
    int topsecneg = 0;
    int prodneg = 0;
    int prodpos = 0;
    int prodmax = 0;
    boolean flag = false;
for (int i = 0; i < a.length; i++) {
        String num = a[i] + "";
        if (num.contains("-")) {
            String array[] = num.split("-");
            num = array[1];
            flag = true;
        } else 
            flag = false;
        if (flag) {
            if (topfirstneg < Integer.valueOf(num)) {
                topsecneg = topfirstneg;
                topfirstneg = Integer.valueOf(num);
            } else if (topsecneg < Integer.valueOf(num)) {

                topsecneg = Integer.valueOf(num);
        }
    }
        else {
            if (topfirstpos < Integer.valueOf(num)) {
                topsecpos = topfirstpos;
                topfirstpos = Integer.valueOf(num);
            }
        else if (topsecpos < Integer.valueOf(num)) {
                topthirdpos = topsecpos;
                topsecpos = Integer.valueOf(num);
            }
            else if (topthirdpos < Integer.valueOf(num)) {
                topthirdpos = Integer.valueOf(num);
            }
        }
    }
    prodneg = topfirstneg * topsecneg;
    prodpos = topfirstpos * topsecpos;

    if (prodneg > prodpos) {
        prodmax = prodneg * topfirstpos;
    } else {
        prodmax = prodpos * topthirdpos;
    }
    return prodmax;
}

public static void main(String a[]) {
    int list[] = { -29, 3, -2, -57, 8, -789, 34 };
MaxProdofThreenumbers t = new MaxProdofThreenumbers();
System.out.println(t.ThreeLargeNumbers(list));

}

}

答案 5 :(得分:1)

n=len(arr1)
    for i in range(0,n):
        arr1[i]=abs(arr1[i])
    arr1.sort()
    return arr1[n-1]*arr1[n-2]*arr1[n-3]

即使此解决方案很简单,它基本上也涉及对数组进行排序,然后取最后三个数字的乘积,然后再进行;数组中的所有值都应为正。这是通过第一个for循环完成的。

答案 6 :(得分:0)

JavaScript代码

function solution(A) {
    if(A.length<3){
        return 0;
    }
    let maxElement = Number.NEGATIVE_INFINITY;
    let idx = null;
    for(let i=0;i<A.length;i++){
        if(A[i]>maxElement){
            maxElement = A[i];
            idx = i;
        }
    }

        A.splice(idx,1);
        A.sort((a,b)=>b-a);
        let n = A.length;
        let positiveMax = A[0]*A[1]*maxElement;
        let negativeMax = A[n-1]*A[n-2]*maxElement;

    return Math.max(positiveMax,negativeMax);    
}        

答案 7 :(得分:0)

可以使用5 variablesO(n)来解决。
Max Product可以通过以下任一方式形成:
1. Max1 * Max2 * Max3
2. Max1 * Min1 * min2
其中Max是最大元素,而Min代表最小值。
这是我的Java解决方案:

int maxProduct(int[] arr) {
    int max1, max2, max3 = Integer.MIN_VALUE;
    max1 = max3;
    max2 = max3;
    int min1 = Integer.MAX_VAULE;
    int min2 = Integer.MAX_VAULE;
    for(int n : arr) {
        if (n <= min1) {            // n is smaller than all
            min2 = min1;
            min1 = n;
        } else if (n < min2) {     // n lies between min1 and min2
            min2 = n;
        }
        if (n >= max1) {            // n is greater than all
            max3 = max2;
            max2 = max1;
            max1 = n;
        } else if (n >= max2) {     // n lies betweeen max1 and max2
            max3 = max2;
            max2 = n;
        } else if (n > max3) {     // n lies betwen max2 and max3
            max3 = n;
        }
    }
}

答案 8 :(得分:0)

在JAVA中可能是这样的:

public final static int maxProizvedenieTrexChisel(Integer m []){
Arrays.sort(m,(g,g1)->g-g1);
System.out.println(Arrays.toString(m));
        int mx1=m[0]*m[1]*m[2];
        int mx2=m[m.length-1]*m[m.length-2]*m[m.length-3];
        int mx3=m[0]*m[1]*m[m.length-1];
        if(mx1>mx2&mx1>mx3)
            return mx1;
                   else if(mx2>mx1&mx2>mx3)
                           return mx2;

        return mx3;

}

答案 9 :(得分:0)

仅当需要3个数字时,此解决方案才适用。如果它是动态的,或者说用户可以要求4或5,那么此解决方案不适合它。

如果不进行排序,则可以通过从数组中找到最多3个数字并乘以3个数字来实现,因为最大乘积需要从数组中获得最大数字。

public class FindOutProductPair {
    public static void main(String args[]) {
        int arr[]= {2,4,3,6,12,1};
//      int arr1[]= {2,4,3,7,6,5,1};
//      int arr1[]= {-1,-4,3,7,6,5,1};
        int arr1[]= {3,2};

        int max1=1,max2=1,max3=1;
        for(int i=0;i<arr1.length;i++) {
            if(max1 < arr1[i]) {
                max3=max2;
                max2=max1;
                max1=arr1[i];
            }else {
                if(max2 < arr1[i]) {
                    max3=max2;
                    max2=arr1[i];
                }
                else {
                    if(max3< arr1[i]) {
                        max3=arr1[i];
                    }
                }
            }
        }
        System.out.println((max3+" "+max2+" "+max1)+" <-- "+(max3*max2*max1));
    }
} 

答案 10 :(得分:0)

以下是我在JavaScript中的解决方案:

function solution(A) {
    A = A.sort((a, b) => b - a);
    var product = A[0] * A[1] * A[2];
    var length = A.length;
    if (A[0] < 0) return product;
    if (A[length - 1] * A[length - 2] * A[0] > product) {
        return A[length - 1] * A[length - 2] * A[0];
    }
    if (A[2] < 0 && length >= 5 && A[3] * A[4] < A[0] * A[1]) {
        return A[2] * A[3] * A[4];
    }
    return product;
}

答案 11 :(得分:0)

def solution(A):
   if len(A) < 3:
      return 0
   A.sort()
   product = A[len(A)-1] * A[len(A)-2] * A[len(A)-3]
   if A[0] < 0 and A[1] < 0:
      if A[0] * A[1] * A[len(A)-1] > product:
         product = A[0] * A[1] * A[len(A)-1]
   return product

答案 12 :(得分:0)

语言- C#

贪婪方法

  

时间复杂度O(n)

 public static int GetHighestProductOfThree(int[] arrayOfInts)
        {

            if (arrayOfInts.Length < 3)
            {
                throw new ArgumentException("Array should be atleast 3 items", nameof(arrayOfInts));
            }

            int highest = Math.Max(arrayOfInts[0], arrayOfInts[1]);
            int lowest = Math.Min(arrayOfInts[0], arrayOfInts[1]);

            int highestProductOf2 = arrayOfInts[0] * arrayOfInts[1];
            int lowestProductOf2 = arrayOfInts[0] * arrayOfInts[1];

            int highestProductOf3 = arrayOfInts[0] * arrayOfInts[1] * arrayOfInts[2];

            for (int i = 2; i < arrayOfInts.Length; i++)
            {
                int current = arrayOfInts[i];
                highestProductOf3 = Math.Max(Math.Max(
                    highestProductOf3,
                    current * highestProductOf2),
                    current * lowestProductOf2);

                highestProductOf2 = Math.Max(Math.Max(
                    highestProductOf2,
                    current * highest),
                    current * lowest);

                lowestProductOf2 = Math.Min(Math.Min(
                    lowestProductOf2,
                    current * highest),
                    current * lowest);

                highest = Math.Max(highest, current);
                lowest = Math.Min(lowest, current);
            }

            return highestProductOf3;
        }

感谢interviewcake.com

Detailed Explanation of this Algorithm

答案 13 :(得分:0)

在JavaScript中

requestAnimationFrame

答案 14 :(得分:0)

对数组进行排序

然后,max将是最后3个或前2个(如果是负数)和最后一个的乘积。

 Arrays.sort(arr);
 int max1 = (arr[n - 1] * arr[n - 2] * arr[n - 3]);
 int max2 = (arr[0] * arr[1] * arr[n - 1]);
 System.out.println(max1 > max2 ? max1 : max2);

答案 15 :(得分:0)

 // Here is a simple java program to find the maximum product of three numbers in  an array.

import java.util.*;
import java.lang.*;

class MOHAN_BERA
{
public static void main(String[] args)
{
    Scanner s = new Scanner(System.in);
        System.out.println("enter the lenth of array:");
        int num1=s.nextInt();
        int[] num2=new int[num1];
        System.out.println("enter the numbers of array:");
        for(int i=0;i<num1;i++)
        {
            num2[i]=s.nextInt();
        }
        Arrays.sort(num2);//sort the array

        long max1=num2[num1-1]*num2[num1-2]*num2[num1-3];//Three last numbers, can be three positive numbers
        long max2=num2[num1-1]*num2[0]*num2[1];//last numbers and first two numbers,can be first two negetive and last one positive numbers
        long max3=num2[0]*num2[1]*num2[2];//for all negetives numbers

        long max=max1;//max1 greatest
        if(max<max2 && max3<max2) //max2 greatest
        {
            max=max2;
        }
        else if(max<max3 && max2<max3)//max3 greatest
        {
            max=max3;
        }
        System.out.println(max);
 }
 }

答案 16 :(得分:0)

u have to consider 3 cases:
1. max 3 positive elements can be the first answer(say 10*20*70).
2. max positive elements multiplied by 2 most negative answers is another candidate(say20*-40*-60).
3.in case where all array elements are negative,3 elements with minimum negative magnitude is answer(-1*-2*-3 in [-1,-2,3,-4,-5]).

for simplicity of question we can merge 1st and 3rd case.
find 3 maximum elements of array, similarly find 2 minimum elements of array.
u will get 2 candidates. Print the maximum of those candidates.

C++ Code:
#include <iostream>
#include <limits.h>
using namespace std;

int main() 
{
    int n;  cin>>n;     int arr[n];     for(int a=0;a<n;a++)     cin>>arr[a];
    bool flag=0;
    int max1=INT_MIN,max2=INT_MIN,max3=INT_MIN;
    int min1=INT_MAX,min2=INT_MAX;

    for(int a=0;a<n;a++)
    {
        if(arr[a]>max1)     {max3=max2;     max2=max1;      max1=arr[a];}
   else if(arr[a]>max2)     {max3=max2;     max2=arr[a];}
   else if(arr[a]>max3)     max3=arr[a];    flag=1;


        if(arr[a]<min1)     {min2=min1;     min1=arr[a];}
   else if(arr[a]<min2)     min2=arr[a];
    }    

    int prod1=INT_MIN,prod2=INT_MIN;
    if(max1>INT_MIN && max2>INT_MIN && max3>INT_MIN)    prod1=max1*max2*max3;
    if(max1>INT_MIN && min1<INT_MAX && min2<INT_MAX)    prod2=max1*min1*min2;

    cout<<max(prod1,prod2)<<endl;                                                
}

答案 17 :(得分:0)

https://stackoverflow.com/users/2466168/maandoo的答案是最好的。

正如他所说,答案是max(l,r)

r. product of last 3 numbers in sorted array
l. product of first two and last number in the sorted array

现在让我详细说明。

我认为这个问题很混乱,因为每个数字都可以是正数,负数和零。通过编程,3状态令人讨厌,你知道!

案例1)给出三个数字

  • 全部使用

案例2)给出四个数字

  • 正数显示为+,负数显示为-
  • 数字从左到右排序。

案例2-1)

2-1) ---- => r (answer is negative)
2-2) ---+ => l (answer is positive)
2-3) --++ => l (answer is positive)
2-4) -+++ => r (answer is positive)
2-5) ++++ => r (answer is positive)

当一个0混合在四个数字中时,它介于两者之间 -+

案例2-2) 假设最小的+实际上是0。

2-1) ---- => r (answer is negative)
2-2) ---0 => l (answer is 0)
2-3) --0+ => l (answer is positive)
2-4) -0++ => r (answer is 0)
2-5) 0+++ => r (answer is positive)

案例2-3)

假设最大-实际为0。

2-1) ---0 => r (answer is 0)
2-2) --0+ => l (answer is positive)
2-3) -0++ => l (answer is 0)
2-4) 0+++ => r (answer is positive)
2-5) ++++ => r (answer is positive)

案例2-4)

如果混合超过两个0,产品将始终为0,因为

-00+

案例2摘要

案例2-1~2-4的回答是一致的。

2-1) r (negative or 0)
2-2) l (0 or positive)
2-3) l (0 or positive)
2-4) r (0 or positive)
2-5) r (positive)

所以,我们实际上不需要担心0。

案例3)超过四个数字

  • 与案例2相同

答案 18 :(得分:0)

假设正面产品大于负面产品,我可以想到以下方式。

  1. 如果数组中的负元素少于两个,那么它很简单,是前3(顶部==正数)元素的乘积。

  2. 如果选择了负数,则至少有2个必须在产品中,因此产品是正数。因此无论如何,最高(正)数字将始终是产品的一部分。

  3. 将最后两个(负数)和第二个和第三个最高值(正数)相乘并进行比较。在这两个价值较高的货币对中,将成为最终产品的一部分以及排在前面的最高正数。

答案 19 :(得分:0)

package interviewProblems;

import interviewProblems.exceptions.ArrayTooSmallException;
import java.util.PriorityQueue;

public class Problem5 {

    public static void main(String[] args) {

        int[] data1 = new int[]{};                                  // error
        int[] data2 = new int[]{1, 5};                              // error
        int[] data3 = new int[]{1, 4, 2, 8, 9};                     // Case: all positive --> 3-max
        int[] data4 = new int[]{10, 11, 12, -20};                   // Case: 1 negative   --> 3-max
        int[] data5 = new int[]{-5, -6, -10, 7, 8, 9};              // Case: 2+ negative  --> 3-max || 1-max 2-small
        int[] data6 = new int[]{-12, -10, -6, -4};                  // Case: all negative --> 3-max

        int[] data7 = new int[]{-10, -10, 1, 3, 2};
        try {
            productOfThree(data2);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        try {
            System.out.println(productOfThree(data3));
            System.out.println(productOfThree(data4));
            System.out.println(productOfThree(data5));
            System.out.println(productOfThree(data6));
            System.out.println(productOfThree(data7));
        } catch (Exception e) {
            System.out.println("You should not see this line");
        }

    }

    //  O(n) time
    //  O(1) memory
    private static int productOfThree(int[] data) throws ArrayTooSmallException {
        if (data.length < 3) {
            throw new ArrayTooSmallException(3 , data.length);
        }

        PriorityQueue<Integer> maxNumbers = new PriorityQueue<>();                  // keep track of 3 largest numbers
        PriorityQueue<Integer> minNumbers = new PriorityQueue<>((x, y) -> y - x);   // keep track of two smallest numbers

        for (int i = 0; i < data.length; i++) {
            maxNumbers.add(data[i]);
            minNumbers.add(data[i]);
            if(maxNumbers.size() > 3) {
                maxNumbers.poll();
            }
            if(minNumbers.size() > 2){
                minNumbers.poll();
            }
        }

        int maxLow = maxNumbers.poll();
        int maxMed = maxNumbers.poll();
        int maxHigh = maxNumbers.poll();

        int minHigh = minNumbers.poll();
        int minLow = minNumbers.poll();

        int possibleProduct1 = maxHigh * maxMed * maxLow;
        int possibleProduct2 = maxHigh * minHigh * minLow;

        return Math.max(possibleProduct1, possibleProduct2);
    }

//  O(n) time
//  O(n) memory
//    private static int productOfThree(int[] data) throws ArrayTooSmallException {
//        if(data.length < 3) {
//            throw new ArrayTooSmallException("Array must be at least 3 long to preform productOfThree(int[] data)");
//        }
//
//        PriorityQueue<Integer> maxNumbers = new PriorityQueue<>((x , y) -> y - x);    // keep track of 3 largest numbers
//        PriorityQueue<Integer> minNumbers = new PriorityQueue<>();                    // keep track of two smallest numbers
//
//        for(int i = 0; i < data.length; i++) {
//            maxNumbers.add(data[i]);
//            minNumbers.add(data[i]);
//        }
//
//        int maxHigh = maxNumbers.poll();
//        int maxMed = maxNumbers.poll();
//        int maxLow = maxNumbers.poll();
//
//        int minLow = minNumbers.poll();
//        int minHigh = minNumbers.poll();
//
//        int possibleProduct1 = maxHigh * maxMed * maxLow;
//        int possibleProduct2 = maxHigh * minHigh * minLow;
//
//        return Math.max(possibleProduct1 , possibleProduct2);
//    }

}

https://github.com/amilner42/interviewPractice/blob/master/src/interviewProblems/Problem5.java

答案 20 :(得分:0)

此问题可以在O(n)时间内完成。

跟踪这5个变量并在每次迭代期间更新它们:

  1. 3个数字的最高产品
  2. 2个数字的最高产品
  3. 最高元素
  4. 2个数字的最低产品
  5. 最低元素
  6. 在最后一次迭代之后,3个数字变量的乘积将是答案。

答案 21 :(得分:-1)

您可以使用Javascript的内置排序功能。需要仔细查找最大三联产品,如果数组的情况下使用-ve数字产品将是第2个和最后一个组合,如果所有+ ve最后3个数字产品将是结果你可以参考我的jsfiddle。该算法的复杂性也是O(nlogn)

var arr=[-10, 3, 5, 6, -20];
function maxTripletProduct(data)
{
  var sortedarr=data.sort(function(a,b){
  return a-b;
})
console.log(sortedarr);

let length=sortedarr.length;
let product1 = sortedarr[length-3]*sortedarr[length-2]*sortedarr[length-1]
let product2=sortedarr[0]*sortedarr[1]*sortedarr[length-1];
if(product2>product1)
  console.log(product2);
else
  console.log(product1);
}
maxTripletProduct(arr);