codility.com上的MaxProductOfThree任务有多种答案,其中大多数都涉及排序算法。
问题是:
给出了由N个整数组成的非空零索引数组A.
问题是找到给定数组中3个元素的最大乘积。
阵列的长度在3到100,000之间
数组A的每个元素都是[-1,000..1,000]
范围内的整数 expected worst-case time complexity is O(N*log(N));
expected worst-case space complexity is O(1),
超出输入存储(不计入输入参数所需的存储空间)。 例如:
a[0] = -3;
a[1] = 7;
a[2] = 2;
a[3] = 1;
a[4] = 5;
a[5] = 7;
最大乘积是[1] * a [4] * a [5] = 245
除了涉及排序的O(n log n)方法之外,是否存在线性时间解决此问题的方法?
答案 0 :(得分:11)
/* The method get the max product of 3 consists in basically find the biggest 3 numbers from the array and the smallest 2 numbers from the array in just 1 iteration over the array. Here is the java code:*/
int solution(int[] a) {
/* the minimums initialized with max int to avoid cases with extreme max in array and false minims 0 minimums returned */
int min1 = Integer.MAX_VALUE;
int min2 = Integer.MAX_VALUE;
/* the same logic for maximum initializations but of course inverted to avoid extreme minimum values in array and false 0 maximums */
int max1 = Integer.MIN_VALUE;
int max2 = Integer.MIN_VALUE;
int max3 = Integer.MIN_VALUE;
//the iteration over the array
for (int i = 0; i < a.length; i++) {
//test if max1 is smaller than current array value
if (a[i] > max1) {
//if a[i] is greater than the biggest max then a chain reaction is started,
// max3 will be max2, max2 will be actual max1 and max1 will be a[i]
max3=max2;
max2=max1;
max1=a[i];
/* in case if current a[i] isn't bigger than max1 we test it to see maybe is bigger than second
max. Then the same logic from above is applied for the max2 amd max3 */
}else if(a[i]>max2){
max3 = max2;
max2 = a[i];
/* finally if current array value isn't bigger than max1 and max2 maybe is greater than max3 */
}else if(a[i]>max3){
max3 = a[i];
}
/* The logic from above with maximums is is applied here with minimums but of course inverted to
discover the 2 minimums from current array. */
if (a[i] < min1) {
min2 =min1;
min1=a[i];
} else if (a[i] < min2) {
min2 = a[i];
}
}
/* after we discovered the 3 greatest maximums and the 2 smallest minimums from the array
we do the 2 products of 3 from the greatest maximum and the 2 minimums . This is necessary
because mathematically the product of 2 negative values is a positive value, and because of
this the product of min1 * min2 * max1 can be greater than max1 * max2 * max3
and the product built from the the 3 maximums. */
int prod1 = min1 * min2 * max1;
int prod2 = max1 * max2 * max3;
//here we just return the biggest product
return prod1 > prod2 ? prod1 : prod2;
}
答案 1 :(得分:2)
有很多不错的答案,但是我认为这个答案有些优雅,100% on codility也很重要。
public static int solution(int[] A) {
Arrays.sort(A);
int F = 0, L = A.length - 1;
int s1 = A[F] * A[F + 1] * A[F + 2];
int s2 = A[F] * A[F + 1] * A[L];
int s3 = A[F] * A[L - 1] * A[L];
int s4 = A[L - 2] * A[L - 1] * A[L];
return Math.max(Math.max(s1, s2), Math.max(s3, s4));
}
答案 2 :(得分:1)
这是一个O(n log n)解决方案。 首先我们对数组进行排序, 然后知道两个具有重要价值的负数会产生更大的正数,我们需要计算数组左边的最大值,以及数组右边的3个元素的乘积,并比较哪一个更大。
以下是示例代码:
// [1,2,3,4] = 24
public int solution(int[] sortedArray) {
Arrays.sort(sortedArray);
int length = sortedArray.length;
int P, Q, R;
int maximumLeft = Integer.MIN_VALUE, maximumRight = Integer.MIN_VALUE;
P = sortedArray[length - 3];
Q = sortedArray[length - 2];
R = sortedArray[length - 1];
maximumRight = P * Q * R;
P = sortedArray[0];
Q = sortedArray[1];
R = sortedArray[length -1];
maximumLeft = P * Q * R;
return maximumRight > maximumLeft ? maximumRight : maximumLeft;
}
不要忘记导入java.util.Arrays; 请参阅此链接以获取Java文件。
答案 3 :(得分:1)
Kotlin 没有排序。
我想知道为什么这里有这么多答案忽略了问题标题“不排序”!
fun solution(A: IntArray): Int {
// write your code in Kotlin
if (A.size < 3) return -1
var max1: Int = Int.MIN_VALUE
var max2: Int = Int.MIN_VALUE
var max3: Int = Int.MIN_VALUE
var min1: Int = Int.MAX_VALUE
var min2: Int = Int.MAX_VALUE
A.forEach {
when {
it > max1 -> {
max3 = max2
max2 = max1
max1 = it
}
it > max2 -> {
max3 = max2
max2 = it
}
it > max3 -> {
max3 = it
}
}
when {
it < min1 -> {
min2 = min1
min1 = it
}
it < min2 -> {
min2 = it
}
}
}
return (min1 * min2 * max1).coerceAtLeast(max1 * max2 * max3)
}
答案 4 :(得分:1)
O(n) 解决方案可能是:
function solution(A) {
let sorted = A.sort((a, b) => a-b);
let max1 = A[A.length - 1] * A[A.length - 2] * A[A.length - 3];
let max2 = A[0] * A[1] * A[A.length - 1];
return Math.max(max1, max2);
}
答案 5 :(得分:1)
这可能有效:
int solution(vector<int>& A) {
// write your code in C++14 (g++ 6.2.0)
int missing = 1;
vector<int> count(A.size());
for (int n = 0; n < A.size(); n++) {
if (A[n] > 0 && A[n] < (A.size() + 1)) {
count[A[n] - 1]++;
}
}
for (int n = 0; n < A.size(); n++) {
if (count[n] == 0) {
break;
}
missing++;
}
return missing;
}
答案 6 :(得分:1)
在排序数组中,最大乘积只有两个可能的选项。
1)最大(最后)三个元素
2)两个最小和最大元素的组合(在负元素的情况下,两个负元素的乘积为正,然后乘以数组的最大元素(如果为正,则可以产生最大乘积))
因此,解决方案是两者中的最大值,没有别的。下方的Codility为100/100。
// you can also use imports, for example:
// import java.util.*;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
import java.util.Arrays;
class Solution {
public int solution(int[] A) {
int N = A.length;
Arrays.sort(A);
/**
* When we sort an array there are two possible options for the largest product
* 1) The largest (the last) three elements
* 2) Combination of two smallest and the largest elements
* Logic of (1): Obvious
* Logic of (2): A pair of negatives multiplied returns a positive, which in combination with
* the largest positive element of the array can give the max outcome.
* Therefore we return the max of options (1) and (2)
*/
return Math.max(A[0] * A[1] * A[N - 1], A[N - 1] * A[N - 2] * A[N - 3]);
}
}
欢呼
答案 7 :(得分:1)
在这里,你不会使用排序,仍然可以获得100%。
#include<limits>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int solution(vector<int> &A) {
//Keep the absolute value for max 2 -ve num . As their mul will be +ve
int abs1 = numeric_limits<int>::min();
int abs2 = numeric_limits<int>::min();
//Keep the max three num irrespective of sign
int max1 = numeric_limits<int>::min();
int max2 = numeric_limits<int>::min();
int max3 = numeric_limits<int>::min();
unsigned int size = A.size()-1;
for (unsigned int i = 0; i <= size ; ++i) {
if(A[i] > 0 ){
} else if(abs(A[i]) >= abs1 ) {
abs2 = abs1;
abs1 = abs(A[i]);
}else if(abs(A[i]) >= abs2 ) {
abs2 = abs(A[i]);
}
if(A[i] >= max1 ){
//Push max1s prev value to max2 and max2's prev val to max3
max3 = max2;
max2 = max1;
max1 = A[i];
} else if(A[i] >= max2 ) {
max3 = max2;
max2 = A[i];
}else if(A[i] > max3 ) {
max3 = A[i];
}
}
// Either max 3 multiplication , or Max 2 negative num whose mul is +ve and the regular max
return max(max1 * max2 * max3, abs1 * abs2 * max1);
}
int main(){
vector<int> test = {-3, 1, 2, -2, 5, 6};
cout << solution(test);
return 0;
}
答案 8 :(得分:0)
这是我的解决方案,我只对所需的排序 https://app.codility.com/demo/results/training68T6KT-NY6/
public int solution(int[] A) {
// write your code in Java SE 8
int result;
for (int i = 0; i < 3; i++) {
for (int j = i; j < A.length; j++) {
if (A[i] < A[j]) {
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < A.length - i; j++) {
if (A[A.length - 1 - i] > A[j]) {
int temp = A[A.length - 1 - i];
A[A.length - 1 - i] = A[j];
A[j] = temp;
}
}
}
if ((A[A.length - 1] < 0) && A[A.length - 1] * A[A.length - 2] > 0) {
result = A[0] * A[A.length - 1] * A[A.length - 2];
if (result > A[0] * A[1] * A[2])
return result;
}
return A[0] * A[1] * A[2];
}
答案 9 :(得分:0)
使用JavaScript(Node.js 8.9.4):
function solution(A) {
// first we order it
A.sort((a, b) => (a - b));
// we see the first two possibilities and we compare them
let val1 = A[A.length - 1] * A[A.length - 2] * A[A.length - 3]
let val2 = A[A.length - 1] * A[0] * A[1]
// we return the higher value
if (val1 > val2) { return val1 } else { return val2 }
}
答案 10 :(得分:0)
得分为100%的Python解决方案
import sys
def solution(A):
if len(A) < 3:
return 0
min_value = sys.maxsize*-1
max_value = sys.maxsize
positive_nus = [min_value]*3
negative_nus =[max_value]*2
for i in range(0,len(A)):
if A[i]> positive_nus[0]:
positive_nus[2] = positive_nus[1]
positive_nus[1]= positive_nus[0]
positive_nus[0] = A[i]
elif A[i] > positive_nus[1]:
positive_nus[2] = positive_nus[1]
positive_nus[1]= A[i]
elif A[i] > positive_nus[2]:
positive_nus[2] = A[i]
if A[i] < negative_nus[0]:
negative_nus[1] = negative_nus[0]
negative_nus[0] = A[i]
elif A[i] < negative_nus[1]:
negative_nus[1] = A[i]
sol1 = positive_nus[0]*positive_nus[1]*positive_nus[2]
sol2 = positive_nus[0]*negative_nus[0]*negative_nus[1]
return max(sol1,sol2)
答案 11 :(得分:0)
python 3,谢谢DanutClapa,我对正数的理解很好,但是您对最后2个负数的澄清才是解决方案。
def solution(arr):
if not arr:
return 0
if len(arr) == 3:
m = 1
for i in arr:
m *= i
return m
else:
max_num = min(arr)
second_max = min(arr)
tercero_max = min(arr)
min_num = max(arr)
min_num_2 = max(arr)
for i in range(0, len(arr)):
if (arr[i] > max_num):
tercero_max = second_max
second_max = max_num
max_num = arr[i]
elif arr[i] > second_max:
tercero_max = second_max
second_max = arr[i]
elif arr[i] > tercero_max:
tercero_max = arr[i]
if arr[i] < min_num:
min_num_2 = min_num
min_num = arr[i]
elif arr[i] < min_num_2:
min_num_2 = arr[i]
return max( max_num * second_max * tercero_max, max_num * min_num * min_num_2)
答案 12 :(得分:0)
@SlobodanAntonijević答案中的JavaScript解决方案
function solution(A) {
let N = A.length;
/* some time sort doesn't work as expected try passing your own
sorting function to sort it in ascending order
*/
A = A.sort((a,b) => (a-b));
return Math.max(A[0] * A[1] * A[N - 1], A[N - 1] * A[N - 2] * A[N - 3]);
}
答案 13 :(得分:0)
没有排序... ES6,但老实说:为什么没有排序?
if (['click', 'keydown'].includes(event.type)) { // Code Implementation Here}
答案 14 :(得分:0)
可以在Codility问题中使用排序。这是一个100%的解决方案。如果没有排序,它就会变得混乱,但绝对可能。
#include<limits>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int solution(vector<int> &A) {
int abs1 = numeric_limits<int>::min();
int abs2 = numeric_limits<int>::min();
sort(A.begin(), A.end());
unsigned int size = A.size()-1;
int temp;
for (unsigned int i = 0; i <= size ; ++i) {
if(A[i] > 0 ) continue;
if(abs(A[i]) >= abs1 ) {
temp = abs1;
abs1 = abs(A[i]);
abs2 = temp;
}else if(abs(A[i]) >= abs2 ) {
abs2 = abs(A[i]);
}
}
return max(A[size] * A[size-1] * A[size-2], abs1 * abs2 * A[size]);
}
int main(){
vector<int> test = {-4, -6, 3, 4, 5};
cout << solution(test);
return 0;
}
答案 15 :(得分:0)
private static int[] rev(int[] validData) {
for (int i = 0; i < validData.length / 2; i++) {
int temp = validData[i];
validData[i] = validData[validData.length - i - 1];
validData[validData.length - i - 1] = temp;
}
return validData;
}
public static int solution(int[] A) {
// write your code in Java SE 8
long p = 0, q = 0, r = 0, max1 = Integer.MAX_VALUE, max2 = Integer.MAX_VALUE, res = 0;
Arrays.sort(A);
A = rev(A);
int start = 0, end = A.length;
//upper bound
p = A[start];
q = A[start + 1];
r = A[start + 2];
max1 = p * q * r;
//lower bound
q = A[end - 1];
r = A[end - 2];
max2 = p * q * r;
return (int) Math.max(max1, max2);
}
有点晚了,但这种方法效率较低,但仍然很快。它反转数组,然后逻辑是,上限是第一个元素*两个连续性,或者第一个元素*两个最后连续,两个中的任何一个应该产生最大值。
答案 16 :(得分:-1)
这是我的c#解决方案。首先对数组进行排序,以获取所需的最大乘积max整数。 对于负整数,我们需要查看排序数组的前两个元素。 此解决方案可获得100%
public int solution(int[] A)
{
var sorted = A.ToList();
sorted.Sort();
var last = sorted[sorted.Count-1]*sorted[sorted.Count-2]*sorted[sorted.Count-3];
var firsttwo = sorted[0]*sorted[1]*sorted[sorted.Count-1];
return Math.Max(last,firsttwo);
}
答案 17 :(得分:-1)
如果有人在乎C。 我之前尝试过quicksort,但由于性能问题获得了88%的结果。 所以我最终得到了一个高效的(100%)但凌乱的代码: https://app.codility.com/demo/results/trainingGT8RQR-FBM/
int solution(int A[], int N) {
int NEG[3]; NEG[0]=0; NEG[1] = 0; NEG[2]=0; int p=-1;
int POS[3]; POS[0] = 0; POS[1] =0; POS[2] = 0; int n=-1;
int MAXIM[3]; MAXIM[0]=-1001; MAXIM[1]=-1001; MAXIM[2]=-1001; int m = -1;
int i =0;
for(i = 0 ; i < N ; i++)
{
if(A[i] < 0 && A[i] < NEG[2])
{
if(A[i] < NEG[0]) { NEG[2] = NEG[1]; NEG[1] = NEG[0];NEG[0] = A[i];}
else if(A[i] < NEG[1]) { NEG[2] = NEG[1]; NEG[1] = A[i];}
else if(A[i] < NEG[2]) NEG[2] = A[i];
if(n < 2) n++;
}
else if(A[i] >= 0 && A[i] > POS[2])
{
if(A[i] > POS[0]) {POS[2] = POS[1]; POS[1] = POS[0]; POS[0]=A[i];}
else if(A[i] > POS[1]) {POS[2] = POS[1]; POS[1] = A[i];}
else POS[2] = A[i];
if(p < 2) p++;
}
if(A[i] <= 0 )
{
if(A[i] > MAXIM[0]){ MAXIM[2]=MAXIM[1];MAXIM[1]=MAXIM[0]; MAXIM[0]=A[i]; if(m<2)m++;}
else if(A[i]>MAXIM[1]){MAXIM[2]=MAXIM[1]; MAXIM[1]=A[i];if(m<2)m++;}
else if(A[i]>MAXIM[2]){MAXIM[2]=A[i]; if(m<2)m++;}
}
}
int max =0, val_set =0;;
if( n >=1 && p>=0 )
{
int tmp = NEG[0] * NEG[1] * POS[0];
if(val_set == 0)
{ max = tmp;
val_set =1;
}
else
if(tmp > max){
max = tmp;
}
}
if( p > 1 )
{
int tmp = POS[0] * POS[1] * POS[2];
if(val_set == 0)
{ max = tmp;
val_set =1;
}
else
if(tmp > max )
{max = tmp;}
}
else
if( n > 1)
{
int tmp = NEG[0] * NEG[1] * NEG[2];
if(val_set == 0)
{ max = tmp;
val_set =1;
}
else
if(tmp > max ){
max = tmp;}
}
if(m>1){
int temp = MAXIM[0] * MAXIM[1] * MAXIM[2];
if(val_set == 0)
{ max = temp;
val_set =1;
}
else if(temp > max){
max = temp;}
}
return max;
}