最低平均两片Codility

时间:2014-02-07 18:42:36

标签: java

给出了由N个整数组成的非空零索引数组A.一对整数(P,Q),使得0≤P<1。 Q&lt; N,被称为数组A的切片(注意切片包含至少两个元素)。切片(P,Q)的平均值是A [P] + A [P + 1] + ... + A [Q]之和除以切片的长度。确切地说,平均值等于(A [P] + A [P + 1] + ... + A [Q])/(Q - P + 1)。
例如,数组A使得:

A[0] = 4
A[1] = 2
A[2] = 2
A[3] = 5
A[4] = 1
A[5] = 5
A[6] = 8

包含以下示例切片:

  • 切片(1,2),其平均值为(2 + 2)/ 2 = 2;
  • 切片(3,4),其平均值为(5 + 1)/ 2 = 3;
  • 切片(1,4),平均值为(2 + 2 + 5 + 1)/ 4 = 2.5。

目标是找到平均值最小的切片的起始位置。

写一个函数:

class Solution { public int solution(int[] A); }

给定由N个整数组成的非空零索引数组A,返回具有最小平均值的切片的起始位置。如果有多个切片具有最小平均值,则应返回此切片的最小起始位置 例如,给定数组A使得:

A[0] = 4
A[1] = 2
A[2] = 2
A[3] = 5
A[4] = 1
A[5] = 5
A[6] = 8

该函数应返回1,如上所述。

假设:

  • N是[2..100,000]范围内的整数;
  • 数组A的每个元素都是[-10,000..10,000]范围内的整数。

复杂度:

  • 预期最坏情况时间复杂度为O(N);
  • 预期的最坏情况空间复杂度为O(N),超出输入存储(不计入输入参数所需的存储空间)。

可以修改输入数组的元素。


这是我最好的解决方案,但在时间复杂度方面显然不是最优的。
有什么想法吗?

public int solution(int[] A) {
    int result = 0;
    int N = A.length;
    int [] prefix = new int [N+1];
    for (int i = 1; i < prefix.length; i++) {
        prefix[i] = prefix[i-1] + A[i-1];
    }
    double avg = Double.MAX_VALUE;
    for (int i = 1; i < N; i++) {
        for (int j = i+1; j <=N; j++) {
            double temp = (double)(prefix[j]-prefix[i-1]) /(double)(j-i+1);
            if (temp < avg) {
                avg = temp;
                result = i-1;
            }
        }
    }
    return result;
}

https://codility.com/demo/results/demo65RNV5-T36/

42 个答案:

答案 0 :(得分:14)

几天前我发布了这个帖子:

  

检查出来:

     

http://codesays.com/2014/solution-to-min-avg-two-slice-by-codility/

     

在那里,他们详细解释了为什么他们的解决方案有效。一世   我自己还没有实现,但我一定会尝试。

     

希望它有所帮助!

但我刚看到它被主持人删除了。他们说这个链接已经死了,但我只是尝试过它并且工作正常。我再次发布它,希望可以验证链接是否正常。

现在我也可以根据我之前提供的codesay链接提供我的实现:https://codility.com/demo/results/demoERJ4NR-ETT/

干杯!

答案 1 :(得分:10)

棘手的部分是在开始编码之前弄清楚确定平均最小切片长度为2或3。 从那里开始更容易,但我有一些重要的注意事项:

  1. 你根本不需要分裂,你可以相乘,这样你就可以在一片长度为6的情况下获得相同的平均值,并完全避免浮动操作

  2. 你不需要在循环中进行除法(或者在我的情况下是乘法),最后一次就足够了。

  3. 如果您必须实际执行此操作,则应始终比较两个浮点数,如下所示: EPSILON = 0.0000001(取决于您所寻找的精度可以是不同的数字)并且如果Math.abs(averageTwo - averageThree)&lt; EPSILON意味着他们是平等的。而且你不需要双精度,浮动就足够了。

  4. 这是我在Java中的解决方案,它在Codility上得到了100%:

    public int solution(int[] A) {
        if (A.length == 2) return 0;
    
        int minSliceTwo = A[0] + A[1];
        int minTwoIndex = 0;
    
        int minSliceThree = Integer.MAX_VALUE;
        int minThreeIndex = 0;
    
        for (int i = 2; i < A.length; i++) {
            int sliceTwo = A[i - 1] + A[i];
            if (sliceTwo < minSliceTwo) {
                minSliceTwo = sliceTwo;
                minTwoIndex = i - 1;
            }
    
            int sliceThree = sliceTwo + A[i - 2];
            if (sliceThree < minSliceThree) {
                minSliceThree = sliceThree;
                minThreeIndex = i - 2;
            }
        }
        int averageMinTwo = minSliceTwo*3;
        int averageMinThree = minSliceThree*2;
    
        if (averageMinTwo == averageMinThree) return Math.min(minTwoIndex, minThreeIndex);
        else return averageMinTwo < averageMinThree ? minTwoIndex : minThreeIndex;
    }
    

答案 2 :(得分:5)

100%得分。的JavaScript。

var min_pos = 0;
var min = Number.MAX_VALUE;

function solution(A) {
  for (var a = 0; a < A.length - 2; a++) {
    process((A[a] + A[a + 1]) / 2.0, a);
    process((A[a] + A[a + 1] + A[a + 2]) / 3.0, a);
  }

  process((A[A.length - 2] + A[A.length - 1]) / 2.0, A.length - 2);
  return min_pos;
}

function process(val, a) {
  if (val < min) {
    min_pos = a;
    min = val;
  }
}

答案 3 :(得分:3)

尽管这似乎是一个比较受欢迎的问题,但基于多少人已经发布了他们的代码,我对2/3元素分片解决方案不满意(继续!在此期间,谁会想到这一点?采访吗?),也没有解释(或没有解释)。

所以我继续寻找其他方法。我发现最大子数组问题(MSP)约为Kanade's algorithm,然后想到了另一种解决方案。

基本问题是(类似于MSP):包含第i个元素的切片的最小平均值是多少?

为了回答这个问题,我们将在第i个元素中查找结束的切片,仅更新其左索引。也就是说,我们必须检查切片A[lft_idx : i]

假设我们知道切片lft_idx的{​​{1}}具有最小的平均值,那么我们有两种可能性:

  1. A[lft_idx : i - 1]的平均值很小。
  2. A[lft_idx : i]的平均值很小(可能的最短切片有2个元素)。

情况1发生的情况是,我们继续增长从A[i - 1 : i]开始的切片。

但是,在情况2中,我们发现增大前一个切片实际上会增加平均值。因此,我们重新开始,然后将切片(lft_idx)的开头“重置”到上一个元素(lft_idx)。从这一点开始,我们有了一个新的 best 大小为2的切片。

最后,我们需要全局最小平均值,因此我们需要跟踪到目前为止的最小值以及该最小值的开始位置(问题只要求这样做,但是我们也可以保存正确的最小值索引)。

i - 1

注意:我在这里使用前缀总和来计算切片平均值,因为这是Codility中出现问题的地方,但是可以很容易地用前切片大小和另一个切片大小的变量替换它乘法。

答案 4 :(得分:3)

我知道http://www.rationalplanet.com/php-related/minavgtwoslice-demo-task-at-codility-com.html提供了迄今为止我所知道的最佳解释和解决方案。 由于这是在前缀sum部分下面,以下是我试图熟悉前缀sum方法的那个。

function solution($A) {
        // write your code in PHP5.3

        $N = count($A);
        if ($N > 100000 || $N < 2 ) {
            return -1;
        } elseif ($N === 2) {
            return 0;
        }

        $presum = array();
        $presum[] = 0;

        $mavg = PHP_INT_MAX;

        $index = 0;
        for ($i = 0; $i < $N; $i++) {                
            $presum[$i+1] = $A[$i] + $presum[$i];
        }

        for ($i = 0; $i < $N-2; $i++) {
            for ($j = $i+1; $j < $i + 3; $j++ ) {
                $avg = ($presum[$j+1] - $presum[$i]) / ($j - $i + 1);

                if ($mavg > $avg) {
                    $mavg = $avg;
                    $index = $i;
                }
            }
        }
        $avg = ($presum[$N] - $presum[$N-2]) / 2;
        if ($mavg > $avg) {
            $index = $N - 2;
        }

        return $index;
}

答案 5 :(得分:2)

   static public int solution(int[] A) {
    // write your code in Java SE 8

    float avg = 0f;
    int min_index = 0;
    int P = 0;
    //formula

    float sums[] = new float[A.length ];

    //sufffix sums
    int prefix = 0;
    for (int i = 0; i < A.length; i += 1) {
        prefix += A[i];
        sums[i] += prefix;
    }
    float min_avg = Float.MAX_VALUE;
    for (int i = 1; i < A.length; i++) {
        avg = (sums[i] - sums[P] + A[P]) / (i - P + 1);
        if (avg < min_avg) {
            min_avg = avg;
            min_index = P;
        }

这个想法很简单,但不是那么简单,A[P] + A[P + 1] + ... + A[Q]) / (Q − P + 1)就是那里的公式,先计算前缀和。

  

公式:min_avg =(前缀[i] - 前缀[P] + A [P])/(i - P + 1)'

        if (A[i] < min_avg) {
            P = i;
        }
    }


    return min_index;


}

答案 6 :(得分:2)

这是使用前缀sums的另一个Java解决方案100/100:

public int solution(int[] A) {
        int len = A.length, result = len - 1, sum = 0;
        int[] prefixSums = new int[len + 1];

        for (int i = 1; i <= len; ++i) {
            prefixSums[i] = prefixSums[i-1] + A[i-1];
        }

        double min = Double.MAX_VALUE, average = 0d;

        for (int P = 0, Q = 1; Q + 1 < prefixSums.length; ++P, ++Q ) {
            sum = prefixSums[Q + 1] - prefixSums[P];
            average = (sum)/(double) 2;

            if (average < min) {
                min = average;
                result = P;
            }

            if ( Q + 2 < prefixSums.length ) {
                sum = prefixSums[Q + 2] - prefixSums[P];
                average = (sum)/(double) 3;

                if (average < min) {
                    min = average;
                    result = P;
                }
            }

        }

        return result;
    }

这是密码链接:https://codility.com/demo/results/demo4S4VJX-WMJ/

答案 7 :(得分:2)

这是一个数学问题......要解决这个问题,你必须要了解切片平均值之间的关系。

我们从问题描述中知道切片的最小长度为2.这个问题的技巧是最小平均切片也不能长于3.所以我们只需要计算切片的平均长度2和3。

要理解为什么最小平均切片不能超过3,请考虑 它长于3的情况......

ex. [-10, 3, 4, -20]

avg(0,3) = -23 / 4 = -5.75 // entire array is -5.75 average
avg(0,1) = -7 / 2 = -3.5 // subslice (0,1)
avg(2,3) = -16 / 2 = -8 // subslice (2,3)

请注意(avg(0,1) + avg(2,3)) / 2 = avg(0,3) 因此,如果avg(0,1) != avg(2,3),则其中一个必须小于另一个。

无论我们分割这个数组的方式是什么,如果切片不完全相同,那么其中一个必须具有比完整切片更低的平均值。玩弄它,你会发现它是真的。那里有数学证明。

答案 8 :(得分:1)

这是一个有效的前缀和实现(100%在Codility中):

import sys

def solution(A):

    n             = len(A)
    pre_sum       = [0] * (n+1)
    min_slice_avg = sys.maxint
    min_slice_idx = 0

    for i in xrange(1,n+1):
        pre_sum[i] = pre_sum[i-1] + A[i-1]

        # calculate at least 2 prefix sums
        if i-2 < 0: continue

        # check prev 3 slices if we have calculated 3 prefix sums
        if i>=3:
            prev_3_slice_avg = (pre_sum[i] - pre_sum[i-3]) / 3.0

            if prev_3_slice_avg < min_slice_avg:
                min_slice_avg = prev_3_slice_avg
                min_slice_idx = i-3

        # check prev 2 slices
        prev_2_slice_avg = (pre_sum[i] - pre_sum[i-2]) / 2.0

        if prev_2_slice_avg <  min_slice_avg:
            min_slice_avg = prev_2_slice_avg
            min_slice_idx = i-2

    return min_slice_idx

答案 9 :(得分:1)

关键是要注意,该问题与在给定数组的长度为2和3的所有切片中找到最小平均值相似。

100%Java解决方案:

    public int solution(int[] A) {
    int N = A.length;
    double minAvg = Integer.MAX_VALUE;
    double sum = 0;
    int result = 0;
    for (int i = 0; i < N - 1; ++i) {
        sum = A[i];
        for (int j = i + 1; j < i + 3 && j < N; ++j) {
            sum += A[j];
            double avg = (sum / (j-i+1));
            if (avg < minAvg) {
                minAvg = avg;
                result = i;
            }
        }
    }
    return result;
}

答案 10 :(得分:1)

int solution(int A[], int N) {
    // write your code in C99 (gcc 6.2.0)
    int i,j,k;
    int min=A[0];
    int index=0;
    float min_ave=10000;// take the maximum value present in an array
    float temp,ave,req;
    
    for(i=0;i<N;i++)
    {
        if(min>A[i])
        min=A[i];
    }
    
    for(i=0;i<N-1;i++)
    {
        ave=(float)(A[i]+A[i+1])/2;
        
        if(min_ave>ave) // for positive integers minimum slice start point is nothing but start point of two elements with minimum average
        {
            min_ave=ave;
            index=i;
        }
        
        if(A[i]<0)// for negative integers we calculate up to the maximum numbers till there is possibility
        {
            k=1;// number of elements up to current average
            temp=A[i];// sum of number of elements up to current average
            for(j=i+1;j<N;j++)
            {
                k++; 
                req=(A[i]*k)-temp;// 'req' required value of element so that average can be less than current minimum average
                temp+=A[j];
                if((temp/k)<min_ave) // average of k elements
                {
                    min_ave=temp/k;
                    index=i;
                }
                if(req<min) // A[j] cannot be less than minimum so break
                break;
            }
        }
        if(min_ave==min)
        break;
    }
    return index;
}

答案 11 :(得分:1)

100%正确性和性能(java)

void sumArray(int[] A, int[] sum) {
    for (int i = 1; i < sum.length; i++) {
        sum[i] = sum[i - 1] + A[i - 1];
    }
}

int getTotalSum(int[] sum, int start, int last) {
    return sum[last + 1] - sum[start];
}

double minav = Double.MAX_VALUE;
int minind = Integer.MAX_VALUE;

public int solution(int[] A) {
    int[] sum = new int[A.length + 1];
    sumArray(A, sum);
    int startpos = 0;
    for (int i = 1; i <= 2; i++) {
        startpos = 0;
        while (startpos + i < A.length) {
            double suma = getTotalSum(sum, startpos, startpos + i);
            double size = (startpos + i) - startpos + 1;
            double av = suma / size;
            if (av <= minav) {

                if (av < minav || startpos < minind) {
                    minind = startpos;
                }
                minav = av;


            }
            startpos += 1;
        }
    }
    return minind;
}

答案 12 :(得分:1)

 public int solution(int[] A)
        {
//C# solution thats getting 100%. Once you find min avg with always within 2   //or 3 elements of moving index its much simpler sol
            int minIndex = 0;
            double minAvgVal = Double.MaxValue;

            for (int i = 0; i < A.Length-2; i++)
            {
                double twoDigitMin = (A[i] + A[i + 1])/2.0;
                if (minAvgVal > twoDigitMin)
                {
                    minAvgVal = twoDigitMin;
                    minIndex = i;
                }

                double threDigitMin = (A[i] + A[i + 1] + A[i+2]) / 3.0;
                if (minAvgVal > threDigitMin)
                {
                    minAvgVal = threDigitMin;
                    minIndex = i;
                }
            }

            double last2Avg = (A[A.Length - 2] + A[A.Length - 1])/2.0;
            if (minAvgVal > last2Avg)
            {
                minIndex = A.Length - 2;
            }

            return minIndex;
        }

答案 13 :(得分:0)

我没有证据证明具有最小平均值的切片只有 2 个元素或 3 个元素,因此我在没有该证据的情况下做出了回答。这个想法是,下一个元素只有在其值低于当前平均值时才能减少当前平均值。

获得 100% 的 Codility。 Link

// you can use includes, for example:
// #include <algorithm>
#include <limits>

// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;

int solution(vector<int> &A) {
    // write your code in C++14 (g++ 6.2.0)
    int result = 0;
    float min_average = std::numeric_limits<float>::max();

    for (vector<int>::iterator it = A.begin(); it < (A.end() - 1); it++) {
        int current_total = *it + *(it + 1);
        unsigned int counter = 2;
        float current_average = float(current_total) / counter;

        while (((it + counter) < A.end())
        && (*(it + counter) < current_average)) {
            current_total += *(it + counter);
            current_average = float(current_total) / (counter + 1);
            counter++;
        }

        if (current_average < min_average) {
            min_average = current_average;
            result = it - A.begin();
        }
    }

    return result;
}

答案 14 :(得分:0)

我认为为什么只有2个和3个子数组需要检查的逻辑(用语言表达)不是那么多,“我们不能使MAV(最小平均值)大于3”,而是如果它更长大于3时,该MAV子数组的起始位置将保持不变。即它不会前进。假设我们已经说过,我们可以拥有长度为1的MAV子数组(尽管'average'不再有意义),我们只需要检查大小为1和2的子数组即可。

为什么会这样,一旦找到给定的起点,尺寸3的子小于尺寸2的子,就无需进一步检查,可以放心地说尺寸3的起点进一步计算的平均值的最小起点是多少? (顺便说一句,当我说给定的“起点”时,我的意思是:-> {4,3,2,1,2,1,1,4}。如果我们选择起点索引3,那么我们可能首先从索引中查看3到索引6作为其自身的数组M,然后在M中找到MAV子数组S的第一个索引,我们只需要检查组合:{1 2}和{1 2 1}。)

所以,我认为逻辑是,首先,您知道将整个数组M除以2,无论拆分位置在哪里,总会给您两个均值相等或小于1的子数组合并后的值等于其父值的平均值=M。现在,如果您看到大小3的子小于大小2,则知道应该进一步子数组[即M之内的较大尺寸的数字变小],同样的事实也告诉您内容的增加率[即相较于除数增加[即,您通过每个添加的后继索引获取的整数/内容]较小。索引号不断增加1],因此,只要这是对的,起始索引就不能移动。

另一方面,如果更大的子数组开始增加,则不必担心最后它们会大于先前检查的子数组大小2 [M之内],因为即使变得更大时,它们仍然始终包含小于先前检查过的大小2的MAV子数组,并且您始终可以选择不包括它们[即在它们之前停下来],并继续声明大小为3的子数组的起始索引作为M的MAV子对象的起始索引。然后在检查所有2和3之后,选择原始数组的每个元素作为“起始点”您将其中最小的作为整个原始阵列的MAV。 (请注意,如果您看到大小为3的子数组等于大小为2的子数组,则不会将起始索引从指向大小为2的子数组的开头更改为指向大小为3的子数组的开头,实际上,那么大小为2的sub将会包含MAV或更确切地说是M中的“第一个” MAV(根据有关Codility的规定)。

我在C#中的解决方案。有点难读,因为它是对先前解决方案的重构,该解决方案具有n * n-1 / 2运行时或类似的运行时间,并且仅使用一个While循环完成,但它使用前缀和。

 public static int solution(int[] A)
        {

            int[] B = new int[A.Length + 1];
            int i = 0;
            int j = 1;
            int copiedVal = A[1];
            A[1] = A[1] + A[0];
            double min = (double)A[1] / 2;
            int pos = 0;
            while (j < A.Length - 1 || (j < A.Length && i == 0))
            {
                B[i + 1] = B[i] + A[i + j];

                if ((double)B[i + 1] / (i + 2) < min)
                {
                    min = (double)B[i + 1] / (i + 2);
                    pos = j - 1;
                }

                if (i == 1)
                {
                    A[j] = copiedVal;
                    j++;
                    copiedVal = A[j];
                    A[j] = A[j] + A[(j - 1)];
                    i = -1;

                }
                i++;

            }

            return pos;
        }

答案 15 :(得分:0)

我在Go中的100%解决方案。 https://app.codility.com/demo/results/trainingV5TF7T-XK6/

func MinAvgTwoSliceSolution(A []int) int {
    // min slice len will always be less than 4 , 
    // imagine a slice of len 4 which can be divided in two slices of 
    // len 2 which either has same avg or 
    // any one of them having lesser avg (the other one will be greater)

    var start int
    min := float64(A[1]+A[0]) / 2

    for i := 2; i < len(A); i++ {
        avg := float64(A[i-1]+A[i]) / 2
        if avg < min {
            min = avg
            start = i - 1
        }

        avg = float64(A[i-2]+A[i-1]+A[i]) / 3
        if avg < min {
            min = avg
            start = i - 2
        }
    }

    return start

}

答案 16 :(得分:0)

答案 17 :(得分:0)

我对python解决方案的看法,不带前缀和。我只对数组做一遍

def solution(A):
    min_avg = 10**5
    index = -1
    for i in range(len(A)-1):
        # slice of size 2
        elem_avg = (A[i] + A[i+1])/2
        if elem_avg < min_avg:
            min_avg = elem_avg
            index = i
            
        # Escape checking slice of size 3 if only 2 elements are left
        if i == len(A)-2: continue
        
        # slice of size 3
        elem_avg_3 = (A[i] + A[i+1]+ A[i+2])/3
        if elem_avg_3 < min_avg:
            min_avg = elem_avg_3
            index = i
            
    return index

答案 18 :(得分:0)

在 Java 中获得 3 * 100% 的最短时间:

double minavg = Double.MAX_VALUE;
        int minSliceIndex = 0;

        for(int p = 0; p < A.length - 1; p++) {
            int sum2 = A[p] + A[p + 1];
            double avg2 = sum2 / 2.0d;
            if(avg2 < minavg) {
                minavg = avg2;
                minSliceIndex = p;
            }

            if(p < A.length - 2) {
                double avg3 = (sum2 + A[p + 2]) / 3.0d;
                if(avg3 < minavg) {
                    minavg = avg3;
                    minSliceIndex = p;
                }
            }
        }
        
        return minSliceIndex;

答案 19 :(得分:0)

得分100%简单解决方案

def solution(A):
    # write your code in Python 3.6
    #initialize  as 0<= P<Q<N(len(A)) is given
    Q=len(A)-1
    avg=(A[0]+A[1])/2
    Mini_Position=0
    
    #Two Slice
  
    for P in range(Q):
        average_two=sum(A[P:P+2])/2.0
        
        if avg > average_two:
            avg=average_two
            Mini_Position=P
    #three slice
    for P in range(Q-1):
        average_three=sum(A[P:P+3])/3.0
      
        if avg >average_three:
            avg =average_three
            Mini_Position=P
        
   
   
    return Mini_Position

答案 20 :(得分:0)

为什么检查长度2和3的切片足够?

这确实是这个问题的根源,并在评论中多次提出。

(Mathjax是not supported here,因此您必须自己从代码格式的文本中解析数学。)

$":",x;.Q.dbp:x;.db.dbm[( vs x}; """ then dbl"/kdb/history/fx" and then use db个数字的平均值,A_n为随后的n个数字的平均值。 可以很容易地检查出这些B_m组合数字的平均值是否为

m

让我们说,通过扩展m + n的切片以包含(n * A_n + m * B_m) / (n + m) 的数目,我们发现了长度为A_n的切片,其平均数更小。 换句话说,我们假设以下不等式成立

B_m

我们可以解决m + n的不等式。将两边分别乘以(n * A_n + m * B_m) / (n + m) < A_n,然后从两边减去B_m。然后除以m + n,我们得出结论:

n * A_n

因此,这意味着m是三个切片中最小的平均值。 我们可以继续重复这个论点。

由于B_m < A_nB_m仍可以用这种方式写成另外两个的总和,因此最小片必须长度> = 4。 或者换句话说,一旦最后一个{因此最小)n >= 2的长度<4,因此长度为2或3,细分就停止了。

答案 21 :(得分:0)

使用Streams最终可以得到100/100的评分!!!!!!

我爱LAMBDAS

return IntStream.range(0, A.length - 2)
            .reduce((i1, i2) -> {
                double iFirst = Math.min((double) (A[i1] + A[i1 + 1]) / 2, (double) (A[i1] + A[i1 + 1] + A[i1 + 2]) / 3);
                double iSecond = Math.min((double) (A[i2] + A[i2 + 1]) / 2, (double) (A[i2] + A[i2 + 1] + A[i2 + 2]) / 3);
                if (A.length - 3 == i2) {
                    double last = (double) (A[i2 + 1] + A[i2 + 2]) / 2;
                    return iFirst <= iSecond && iFirst <= last ? i1 : iSecond <= last ? i2 : i2 + 1;
                }
                return iFirst <= iSecond ? i1 : i2;
            }).orElse(0);

答案 22 :(得分:0)

这是我在C ++中的方法(仅包含2个元素的切片,我们应该对更多元素进行处理吗?)

//search functions
function citySearch(req, res) {
  var noMatch = null;
  if (req.query.search) {
    const regex = new RegExp(escapeRegex(req.query.search), 'gi');
    // Get all homes from DB
    Home.find({ city: regex }, function (err, allHomes) {
      if (err) {
        console.log(err);
      } else {
        if (allHomes.length < 1) {
          noMatch = "No homes match that query, please try again.";
        }
        var linkRoute = "homes/index";
        var cityObj = { linkRoute: "homes/index", homes: "homes:allHomes", noMatch: "noMatch: noMatch" };
        //return object instead of res.render statement
        return cityObj;
        //res.render("homes/index",{homes:allHomes, noMatch: noMatch});
      }
    });
  } else {
    // Get all homes from DB
    Home.find({}, function (err, allHomes) {
      if (err) {
        console.log(err);
      } else {
        var linkRoute = "homes/index";
        var linkObj = { linkRoute: "homes/index", homes: "homes:allHomes", noMatch: "noMatch: noMatch" };
        //return object instead of res.render statement
        return linkObj;   // Return linkObj instead of cityObj
        //res.render("homes/index",{homes:allHomes, noMatch: noMatch});
      }
    });
  }
}

答案 23 :(得分:0)

我现在只想在Java中复制粘贴我的解决方案。但是想说,关于问题和我的观点。首先,这是我对Codility最重的任务。已经用100%的完美分数解决了难题,但这是不同的。 Codility的任务说明如果比较棘手,可能会导致(我的情况)错误的解决方案。首先,我知道切片必须至少为2,但要精确到多长时间。我之前使用前缀和,并在此之前的部分中解决了问题。但是我在这里现在从哪里开始。 然后从YouTube朋友那里得到提示,在她的视频中(她是python上瘾者,但逻辑是我缺乏我所需要的),她没有给出解决方案,只给出了n%的部分解决方案,并提示了一个解决方案..您“需要检查切片2和3”(我认为我可以观察任务的年龄,因此请勿尝试)。

她的视频 https://www.youtube.com/watch?v=w0eFQwiKY7k&lc=z22kcx1jbm3dgxmmtacdp43aah2bhysshyiae2xmrzdw03c010c.1582810577807791

最好的前缀加视频永远存在(非常有帮助!) https://www.youtube.com/watch?v=scD312I7kkE

class Solution {
    public int solution(int[] A) {
        int ind = 0;
        if (A.length > 3) {
            //make min value double increase corectness to  80%
            double min = (double) (A[0] + A[1]) / 2;
            ind = 0;
            for (int n = 1; n < A.length; n++) {
                A[n] = A[n] + A[n - 1];
            }
            for (int m = 1; m < A.length - 1; m++) {
                if (m + 2 < A.length) {
                    if ((double) (A[m + 2] - A[m - 1]) / 3 < min) {
                        min = (double) (A[m + 2] - A[m - 1]) / 3;
                        ind = m;
                    }
                }
                if ((double) (A[m + 1] - A[m - 1]) / 2 < min) {
                    min = (double) (A[m + 1] - A[m - 1]) / 2;
                    ind = m;

                }
            }
            //added
            if ((double) (A[2]) / 3 < min) {
                min = (double) (A[2]) / 3;
                ind = 0;
            }
            if ((double) (A[1]) / 2 < min) {
                min = (double) (A[1]) / 2;
                ind = 0;
            }
            return ind;
        }
        return ind;
    }
}

希望这会有所帮助, Nenad,祝您编程愉快

答案 24 :(得分:0)

我的 Python 答案 100% 的可编码性:

def solution(A):
amin = sum(A)/len(A)
imin = 0

for i in range(0, len(A)-1):
    sij = A[i]

    for j in range(i+1, i+3):
        if j < len(A):
            sij += A[j]
            aij = sij/(j-i+1)

            if aij < amin:
                amin = aij
                imin = i

return imin

答案 25 :(得分:0)

python解决方案,几乎没有解释,希望对您有所帮助。 Codility Python 100%

import sys


def solution(A):
"""
https://app.codility.com/demo/results/training3K95ND-KGH/
100%
Idea-
Idea is to calculate the prefix some and find out the average as per given formula in this problem and determine minimum slice starting index
Prefix sum - is used to avoid the two loops to calculate the sum of array Items
Find min average from P to Q in array and store the minimum index and say it as average of slice from p to q
Objective is to find minimum average of other slice, the next slice can be [next q+1 and either include  p,q,q+1 p or exclude q,q+1]
We can exclude the slice calculated so far if the current item is less than the average

   """

min_index = 0
print(A)
# why prefix some? - just to calculate the some between two places without using two loops
prefix_sum = [0] * len(A)
prefix_sum[0] = A[0]
for i in range(1, len(A)):
    prefix_sum[i] = prefix_sum[i - 1] + A[i]
print(prefix_sum)

min_avg = sys.float_info.max
# start from slice p ie. from start, this is start and act as P in problem statement and Q would be the q_end_index as shown below
slice_p_from_index = 0
for q_end_index in range(1, len(A)):
    # for q_end_index = 1 - at this time calculating average from 0 to 1
    # as per problem statement (A[P] + A[P + 1] + ... + A[Q]) / (Q − P + 1)
    print("From P:slice_p_from_index= " + str(slice_p_from_index) + "  To Q: i= " + str(q_end_index) + " slice " + str(A[slice_p_from_index:q_end_index + 1]))
    print("Slice length " + str(q_end_index - slice_p_from_index + 1))
    # get the some for position P,Q - ie. from slice_p_from_index to i positions and davide by the slice length
    average = (prefix_sum[q_end_index] - prefix_sum[slice_p_from_index] + A[slice_p_from_index]) / (q_end_index - slice_p_from_index + 1)
    # check for minimum average so far
    if average < min_avg:
        min_avg = average
        # hold the index for minimum average value
        min_index = slice_p_from_index

    print("min_avg " + str(min_avg))
    # this is to find out the next starting position for slice_p_from_index
    # idea is to skip all the items found so far up to q_end_index-1, to skip and start from q_end_index we have to proof that the next slice min average
    # can be less than the current minimum average
    # that can only happen if and only if current Item A[q_end_index] is less than the minimum average
    # if so we start taking array slice from current Item A[q_end_index] and make slice with next Item
    print("Index = " + str(q_end_index) + " Item " + str(A[q_end_index]))
    if A[q_end_index] < min_avg:
        print("min index found....Item < min_avg, slice_p_from_index changed to Index")
        slice_p_from_index = q_end_index
    print("")
return min_index

运行-

"""
Run - 
[4, 2, 2, 5, 1, 5, 8]
[4, 6, 8, 13, 14, 19, 27]
From P:slice_p_from_index= 0  To Q: i= 1 slice [4, 2]
Slice length 2
min_avg 3.0
Index = 1 Item 2
min index found....Item < min_avg, slice_p_from_index changed to Index

From P:slice_p_from_index= 1  To Q: i= 2 slice [2, 2]
Slice length 2
min_avg 2.0
Index = 2 Item 2

From P:slice_p_from_index= 1  To Q: i= 3 slice [2, 2, 5]
Slice length 3
min_avg 2.0
Index = 3 Item 5

From P:slice_p_from_index= 1  To Q: i= 4 slice [2, 2, 5, 1]
Slice length 4
min_avg 2.0
Index = 4 Item 1
min index found....Item < min_avg, slice_p_from_index changed to Index

From P:slice_p_from_index= 4  To Q: i= 5 slice [1, 5]
Slice length 2
min_avg 2.0
Index = 5 Item 5

From P:slice_p_from_index= 4  To Q: i= 6 slice [1, 5, 8]
Slice length 3
min_avg 2.0
Index = 6 Item 8

Solution 1

“”“

我希望它可以帮助至少一位用户。

答案 26 :(得分:0)

一种更具可读性的 Python 解决方案,其得分为100%:

预先计算前缀和:

def prefix_sum(A):
    n = len(A)
    P = [0] * (n + 1)
    for k in range(1, n + 1):
        P[k] = P[k - 1] + A[k - 1]
    return P

这需要像之前建议的那样使用2和3个元素切片,并存储当前的最小平均值和起始索引

def solution(A):
    pref = prefix_sum(A)
    min_mean = 10000
    min_idx_from = 0
    for i in range(len(A)):
        for j in range(i+1,min(i+3,len(A))):
            mean = (pref[j+1] - pref[i]) / (j-i+1)
            if mean < min_mean:
                min_mean = mean
                min_idx_from = i
    return min_idx_from

测量时间:

import random
random.seed(123)
n = 1000
A = [random.randint(-10000, 10000) for _ in range(n)]
%timeit solution(A)
# 1.01 ms ± 3.89 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Codility链接:

https://app.codility.com/demo/results/trainingAK963Y-3NR/

答案 27 :(得分:0)

Python解决方案(100%通过)

def find_2_lowers(A):
    total = 10001 + 10001
    x_pos = 0
    y_pos = 0
    for i,j in zip(range(len(A)), range(1, len(A))):
        if j == len(A):
            return x_pos, y_pos, total
        if A[i] + A[j] == total:
            continue #ignoring the more deeply index
        elif A[i] + A[j] < total:
            total = A[i] + A[j]
            x_pos = i
            y_pos = j


    return x_pos, y_pos, total

def find_3_lowers(A):
    total = 10001 + 10001 + 10001
    x_pos = 0
    y_pos = 0
    z_pos = 0
    for i,j,k in zip(range(len(A)), range(1, len(A)),range(2, len(A))):
        if k == len(A):
            return x_pos, y_pos, z_pos, total
        if A[i] + A[j] + A[k] == total:
            continue #ignoring the more deeply index
        elif A[i] + A[j] + A[k] < total:
            total = A[i] + A[j] + A[k]
            x_pos = i
            y_pos = j
            z_pos = k

    return x_pos, y_pos, z_pos, total

def solution(A):
    if len(A) <= 2:
        return 0

    x2,y2,total2 = find_2_lowers(A)
    x3,y3,z3,total3 = find_3_lowers(A)

    #print("x2,y2,total2 ", x2,y2,total2 )
    #print("x3,y3,z3,total3 ", x3,y3,z3,total3 )

    if total2/2 < total3/3:
        return x2
    elif total2/2 == total3/3:
        return min(x2, x3)
    return x3

答案 28 :(得分:0)

100%Scala解决方案

  def solution(a: Array[Int]): Int = {
    val n = a.length
    var min = Double.MaxValue
    var minPos = 0
    for (i <- 0 to n - 2) {
        val sum2: Double = a(i) + a(i+1)
        var avg = sum2 / 2
        if (i < n - 2) {
            avg = Math.min(avg, (sum2 + a(i+2)) / 3)
        }
        if (avg < min) {
            min = avg
            minPos = i
        }
    }
    minPos
  }

答案 29 :(得分:0)

基于Kanade算法的C ++,前缀和为https://app.codility.com/demo/results/training66V2HC-V6S/

https://www.headout.com/tour/5696/united-states/las-vegas/eldorado-canyon-techatticup-mine-tour-premium-group-tour?utm_source=uvergo&utm_medium=ref&utm_campaign=meta

如您所见,sumOfTwo是使用前缀和的示例。

答案 30 :(得分:0)

在功能编程语言FP(例如Scala或Haskell)中,前缀和是通过Scan高阶函数提供的。

在我们的例子中,附加的HOF函数_ + _等同于lambda函数(x, y) => x + y

https://en.wikipedia.org/wiki/Prefix_sum

FP提供了一种更简单的方式来表达我认为更容易理解的算法。

即使使用recursion和一些解释,该解决方案也获得了100%的评分。

https://app.codility.com/demo/results/trainingBZJU4M-NXE/

  def solution(a: Array[Int]): Int = {

    val n: Int = a.length

    /**
      * Let's initialize the prefixSums Array
      */
    val prefixSums: Array[Int] = a.scan(0)(_ + _)

    /**
      * Let's look for a Minimum that has:
      * a position and an average
      * (i.e. Product Type Data Structure)
      */
    case class Minimum(position: Int, average: Float)

    /**
      * Based on a Slice: Position [P] and [Q]
      * Q here is represented by its size [P - Q] (2 or 3)
      * CAPTURE only if there is a change in the minimum average
      */
    def average(p: Int, q: Int, min: Minimum): Minimum = {
      val average: Float = (prefixSums(p + q) - prefixSums(p)) / q.toFloat
      if (average < min.average) min.copy(position = p, average = average) else min
    }

    /**
      * Let's start with the first position
      * and a max average value
      */
    val init = Minimum(position = 0, average = Float.MaxValue)

    /**
      * Let's fold through the A Array indices minus one
      * (paying attention to the slice size)
      *
      * while capturing the minimum average.
      * If Q size reaches 3 (instead of regular slice tuple:
      *    capture the last minimum average
      *    otherwise return the current minimum average
      * give the minimal position
      */
    (0 until n - 1).toList
      .foldLeft(init) { (min, p) =>
        val currentMin = average(p, 2, min)
        if (p < n - 2) average(p, 3, currentMin) else currentMin
      }.position

  }

答案 31 :(得分:0)

答案 32 :(得分:0)

C ++解决方案,对我来说很好用

{{1}}

答案 33 :(得分:0)

我认为检查长度为2和3的切片背后有逻辑。根据问题陈述,切片的最小长度可以是2.

  

因此,在切片增长到2个最小长度切片之前,我们可以添加到切片的最小元素是1.所以我们必须检查长度为2和3的切片。我们不需要超过长度为3的切片,因为它最终将有2片长度为2。

让我们再举一个例子,假设Slice的长度最小为3.现在在这种情况下,根据我们的公式,我们需要从长度为3到5的切片进行检查。考虑以下数组

  

-30,-1,-1,-1,-30,-1,-1,1,2,3,4,45

这里,如果我们采用Slice(0,4),平均值是-12.6(这是最小值)。尝试所有其他组合(长度3和4)并玩它。你会明白的。

如果我们采取长度为6的切片 切片(0,5),平均值-10.66,等于切片(0,2)和切片(3,5)的平均值

不使用前缀总和(100%得分)的解决方案

    public int solution(int[] A)    {
    float tempAverage,finalAverage = Float.MAX_VALUE;
    int startLocation = 0;
    int lengthOfTheSlice = 0;
    for(int i=0; i < A.length -1; ++i)  {
        tempAverage = (float)(A[i] + A[i+1])/2;
        if(tempAverage < finalAverage)    {
            finalAverage = tempAverage;
            startLocation = i;
            lengthOfTheSlice =2;
        }
    }
    for(int i=0; i < A.length -2; ++i)  {
        tempAverage = (float)(A[i] + A[i+1]+ A[i+2])/3;
        if(tempAverage < finalAverage)    {
            finalAverage = tempAverage;
            startLocation = i;
            lengthOfTheSlice =3;
        }
    }
    System.out.print("Length of the slice \t"+lengthOfTheSlice);
    return startLocation;
}

答案 34 :(得分:0)

这是我在Java中的实现。我得到了100%。 该算法是相同的(2和3个连续值的总和),除了我没有使用addidional内存作为前缀和。 我们不需要一次性所有的总和,因此我们只能保持当前的总和,并在我们向右的时候从总和中减去最左边的元素。

public int solution(int vect[]) {

    double minAvg = (vect[0] + vect[1]) / 2.;
    int minIndex = 0;

    double tempAvg = minAvg;
    int tempSum = vect[0] + vect[1];
    int tempIndex = 0;
    int tempLength = 2;

    double newAvg;
    int newSum, newIndex;

    for(int j=2; j<vect.length; ++j) {
        ++tempLength;
        tempSum += vect[j];
        tempAvg = (double)tempSum / tempLength;


        newSum = tempSum - vect[tempIndex];
        newIndex = tempIndex+1;
        newAvg = newSum/(j-newIndex+1.);

        while(newAvg < tempAvg && newIndex < j) {
            tempIndex = newIndex;
            tempSum = newSum;
            tempAvg = newAvg;
            --tempLength;

            newSum = tempSum - vect[tempIndex];
            newIndex = tempIndex+1;
            newAvg = newSum/(j-newIndex+1.);
        }

        if (tempAvg < minAvg) {
            minIndex = tempIndex;
            minAvg = tempAvg;
        }
        else if(tempAvg > minAvg && j-tempIndex>1) {
            tempIndex = j;
            tempLength = 1;
            tempSum = vect[j];
        }
    }
    return minIndex;
}

答案 35 :(得分:0)

python中的100%:

def solution(A):
 if(len(A) < 2):
     return 0;
 MinAvg=float(A[0]+A[1])/float(2);
 Index=0;
 for nn in range(1,len(A)-1):
     Avg=float(A[nn]+A[nn+1])/float(2);
     if(Avg<MinAvg):
         MinAvg=Avg;
         Index=nn;     
 for nn in range(0,len(A)-2):
     Avg=float(A[nn]+A[nn+1]+A[nn+2])/float(3);
     if(Avg<MinAvg):
         MinAvg=Avg;
         Index=nn;                    
 return Index;     
pass 

解释:

平均和比较2个连续元素几乎得到最大分数。因为当一个元素添加元素时,如果平均值较小,那么接下来的两个元素将具有较小的平均值。

之后只剩下3个元素的异常,如[-1,2,4,-1,2,-1]。

答案 36 :(得分:0)

这是我在C ++中的解决方案,基于证明最小切片必须存在长度为2或3,请参见https://codesays.com/2014/solution-to-min-avg-two-slice-by-codility/

的证明

在Codility上获得100%的正确率和速度得分。无需分配任何内存来解决此问题,因此算法空间为O(1),不计算输入向量。

int solution(vector<int> &A) {
    int N             = A.size();
    int minSliceStart = 0;

    if (N > 2) {
        // Min Slice must be of length 2 or 3.
        // If Min Slice is longer, 
        //    it must be divisible into smaller parts of equal average
        int min_2_slice_start = 0;
        int min_3_slice_start = 0;
        int min_2_slice_sum   = A[0]+A[1];
        int min_3_slice_sum   = A[0]+A[1]+A[2];

        for(int i=0; i<(N-1); i++) {
            int cur_2_slice_sum = A[i]+A[i+1];

            // check if the current 2-slice sum is smaller
            if (cur_2_slice_sum < min_2_slice_sum) {
                min_2_slice_sum   = cur_2_slice_sum;
                min_2_slice_start = i;
            }

            // check if the current 3-slice sum is smaller
            if (i<(N-2)) {
                int cur_3_slice_sum = A[i]+A[i+1]+A[i+2];
                if (cur_3_slice_sum < min_3_slice_sum) {
                    min_3_slice_sum   = cur_3_slice_sum;
                    min_3_slice_start = i;
                }
            }
        }

        #ifdef Want_Debug_Statements
            cout << "2-Slice: start=" << min_2_slice_start << ", sum=" << min_2_slice_sum <<endl;
            cout << "3-Slice: start=" << min_3_slice_start << ", sum=" << min_3_slice_sum <<endl;
        #endif

        // If 2-slice or 3-slice are equal, take the first one.
        // Note: rather than computing averages by dividing,
        // multiple each side by the other denominator instead & compare.
        if (min_2_slice_sum*3 == min_3_slice_sum*2) {
            if (min_2_slice_start < min_3_slice_start)
                minSliceStart = min_2_slice_start;
            else
                minSliceStart = min_3_slice_start;
        } else {
            if (min_2_slice_sum*3 < min_3_slice_sum*2)
                minSliceStart = min_2_slice_start;
            else
                minSliceStart = min_3_slice_start;
        }
    }

    return minSliceStart;
}

答案 37 :(得分:0)

private static int solution(int[] a) {
    // TODO Auto-generated method stub

    int sum=0;
    int absSum=0;
    int minAbsSlice=10000;

    for(int i=0;i<a.length;i++){
        sum=a[i];
        for(int j=1;j<a.length;j++){
            if(j>=i){
                absSum=sum+a[j];
                if(absSum<sum){
                    sum=absSum;
                    absSum=Math.abs(absSum);

                }else{

                    absSum=Math.abs(sum);
                    sum=absSum;
                }
            }
        }
        sum=0;
        if(minAbsSlice<absSum){
            minAbsSlice=minAbsSlice;
        }else{
            minAbsSlice=absSum;
        }

    }
    return minAbsSlice;
}

答案 38 :(得分:0)

我的答案得分100

public class MinAvgTwoSlice {

public static void main(String[] args) {

    System.out.println(new MinAvgTwoSlice().solution(new int[] {4, 2, 2, 5, 1, 5, 8} ));    
}

public int solution(int[] A) {

    double minAvg = 100000;
    int index=0;

    if(A.length<=2) {

        return 0;
    }

    for(int i=0;i<A.length-2;i++) {

        if((A[i]+A[i+1])/2.0<minAvg) {
            minAvg=(A[i]+A[i+1])/2.0;
            index=i;
        }

        if((A[i]+A[i+1]+A[i+2])/3.0<minAvg)  {

            minAvg=(A[i]+A[i+1]+A[i+2])/3.0;
            index=i;
        }
    }

    int aMax = A.length-2;

    if((A[aMax]+A[aMax+1])/2.0<minAvg) {

        minAvg=(A[aMax]+A[aMax+1])/2.0;
        index=aMax;
    }

    return index;
}
}

谢谢:基于codesays.com提供的逻辑

答案 39 :(得分:0)

我在C#中得到了100%。试试这个https://codility.com/demo/results/demoV25DUE-9A8

    public static int solution(int[] A)
    {
        float min_avg = (A[0] + A[1]) / 2;
        int minpos = 0;

        for (int i = 0; i < A.Length-2; i++)
        {
            float firsttwo = (float)(A[i] + A[i+1])/2;

            if (firsttwo < min_avg)
            {
                min_avg = firsttwo;
                minpos = i;
            }

            float three = (float)(A[i] + A[i+1] + A[i+2])/3;
            if (three < min_avg)
            {
                min_avg = three;
                minpos = i;
            }

            float lasttwo = (float)(A[i + 1] + A[i + 2]) / 2;
            if (lasttwo < min_avg)
            {
                min_avg = lasttwo;
                minpos = i+1;
            }
        }

        return minpos;
    }

答案 40 :(得分:0)

这是Go实现:

func Solution(A []int) int {
    if len(A) < 2 {
        return -1
    }

    result := 0
    minAvg := float64(A[0]+A[1]) / 2
    var curAvg float64
    for index := 0; index < len(A)-2; index++ {
        curAvg = float64(A[index]+A[index+1]) / 2
        if curAvg < minAvg {
            minAvg = curAvg
            result = index
        }

        curAvg = float64(A[index]+A[index+1]+A[index+2]) / 3
        if curAvg < minAvg {
            minAvg = curAvg
            result = index
        }
    }

    curAvg = float64(A[len(A)-2]+A[len(A)-1]) / 2
    if curAvg < minAvg {
        minAvg = curAvg
        result = len(A) - 2
    }

    return result
}

答案 41 :(得分:0)

这是我用C编写的解决方案(得分100%)

#include <string.h>

int solution(int A[], int N) {
    // write your code in C99

    int *p, i;
    float minAvg, tmpAvg;
    int index=0;

    p=malloc(sizeof(int)*(N+1));
    memset(p, 0, sizeof(int)*(N+1));

    if(N == 2) {
        return 0;
    }

    *p=0;

    //Building prefixes vector
    for(i=0;i<N;i++) {
        *(p+i+1)=*(p+i)+A[i];
    }

    minAvg=*(p+N)/(float)(N);

    for(i=0; i<N-1; i++) {
        tmpAvg=(*(p+i+2)-*(p+i))/(float)(2);
        if (tmpAvg < minAvg) {
            minAvg=tmpAvg;
            index=i;
        }
    }

    for(i=0; i<N-2; i++) {
        tmpAvg=(*(p+i+3)-*(p+i))/(float)(3);
        if (tmpAvg < minAvg) {
            minAvg=tmpAvg;
            index=i;
        }
    }

    free(p);
    return index;
}