磁带均衡Codility培训计划

时间:2014-08-08 08:06:36

标签: java

我提交了Codility中Tape Equilibrium问题的解决方案。 [Codility培训] [1]

问题描述如下:

  

给出了由N个整数组成的非空零索引数组A.数组A表示磁带上的数字。   任何整数P,使得0 <0。 P&lt; N,将此磁带分成两个非空部分:A [0],A [1],...,A [P-1]和A [P],A [P + 1],...,A [N - 1]。   两部分之间的差异是:|(A [0] + A [1] + ... + A [P - 1]) - (A [P] + A [P + 1] + .. 。+ A [N - 1])|   换句话说,它是第一部分之和与第二部分之和的绝对差值。

我提交的解决方案是:

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

    long d = A[0] - A[A.length-1];
    int l = 1;
    int r = A.length -2;

    while(l <= r) {
      if (Math.abs(d + A[l]) < Math.abs(d - A[r])) {
        d += A[l];
        l++;
      }
      else {
        d -= A[r];
        r--;
      }
    }
    return (int) Math.abs(d);
  }
}

我达到了85%的准确率但无法纠正某些用例。有人可以帮我找到这个解决方案的错误。感谢

21 个答案:

答案 0 :(得分:3)

以下是我的100%解决方案:

class Solution {
public int solution(int[] A) {
    // write your code in Java SE 8
    // int idx = 0;
    int sumPre = A[0];
    int sumPost = 0;
    for (int i = 1; i < A.length; i++) {
        sumPost += A[i];
    }
    int difMin = Math.abs(sumPost - sumPre);
    int tempSub = 0;
    for (int i = 1; i < A.length - 1; i++) {
        sumPre += A[i];
        sumPost -= A[i];
        tempSub = Math.abs(sumPost - sumPre);
        if (tempSub < difMin) {
            difMin = tempSub;
            // idx = i+1;

        }
    }
    return difMin;
}
}

我找不到他们的测试输入,但我发现一个奇怪的事情是当&#34; for(int i = 1; i&lt; A.length - 1; i ++)&#34;改为&#34; for(int i = 1; i&lt; A.length; i ++)&#34 ;,然后它将触发两次错误的运行...所以它仍然必须是边界值问题。 如果任何人发现测试输入可能会破坏有效性,请与我们分享,谢谢。

警告:{1,-1}确实触发了问题,因为P&lt; N,所以至少应该在右边部分留下一个元素。 - &GT;根据问题定义,{1,-1},{}不是有效的解决方案。 问题解决了。

答案 1 :(得分:1)

截至 2021 年 5 月,C# 和 Linq 版本 100%:

  public int solution(int[] A) 
    {

      int left = A[0];
      int right = A.Skip(1).Aggregate((c,x)=> c+=x);
      int min = Math.Abs(left-right);

      for(int i=1; i < A.Length-1; i++) 
      {
        left+=A[i];
        right-=A[i];
        min = Math.Min(min,Math.Abs(left-right));
      }
 
      return min;
    }

答案 2 :(得分:1)

我分享了100%得分的Java解决方案:

class Solution {
public int solution(int[] A) {
        final int size = A.length;
        long sumMin = (int)A[0];
        long sumMax = 0;
        for (int i = 1; i < size; i++) {
            sumMax += (int)A[i];
        }
        int minDif = (int)Math.abs(sumMax - sumMin);
        for (int i = 1; i < size; i++) {
            int dif = (int)Math.abs(sumMax - sumMin);
            if (dif < minDif) {
                minDif = dif;
            }
            sumMin += A[i];
            sumMax -= A[i];
        }
        return minDif;
    }
}

技巧是将数组循环两次,复杂度为2N,即O(N)。

加法结果应该是“长”的。为了不出现极端问题。

答案 3 :(得分:1)

我也试过,只得到83%。我的解决方案:

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

        int[] leftSums = new int[A.length];
        for (int i = 0; i < leftSums.length; i++) {
            leftSums[i] = 0;
        }

        int sum = 0;
        for (int i = 0; i < A.length; i++) {
            sum  += A[i];
            leftSums[i] = sum;
        }
        /*
        for (int i = 0; i < leftSums.length; i++) {
            if (i == 0) {
                System.out.print("Left Sums Array is : [");
            }

            if (i == leftSums.length - 1) {
                System.out.println(leftSums[i] + "]");
            }
            System.out.print(leftSums[i] + ", ");
        }
        */
        final int total = sum;
        //System.out.println("Total is " + total);
        int minDiff = Integer.MAX_VALUE;
        int currDiff = 0;
        for (int i = 0; i < leftSums.length; i++) {
            currDiff = Math.abs(leftSums[i] - (total - leftSums[i]));
            if (currDiff < minDiff) {
                minDiff = currDiff;
            }
        }

        return minDiff;
    }
}

以下是那些因正确性而失败的人。 双 两个要素1.280 s错误的回答 预计2000年为0

小 小元素1.304 s错误的答案 得到0预期20

我测试了自己的2个元素,它对我有用。

答案 4 :(得分:0)

这是scala的100%。

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

    //get the whole sum
    val allSum = A.sum

    //calculate left and right sum
    var sumLeft = A(0)
    var sumRight = allSum - sumLeft

    //set initial diff for P=1
    var minDiff = math.abs(sumLeft-sumRight)  //difference

    // loop for all P after the initial P position
    for(p <- 1 to A.length-2){

      //recalculate values
      sumLeft += A(p)
      sumRight -= A(p)

      if(math.abs(sumLeft-sumRight) < minDiff){
        // if difference is smaller then save new min diff
        minDiff = math.abs(sumLeft-sumRight)
      }

    }

    minDiff
  }

效果:https://codility.com/demo/results/trainingZNZCZN-AGC/

答案 5 :(得分:0)

尚无人发布Javascript解决方案,因此以下是我的评论:

// you can write to stdout for debugging purposes, e.g.
// console.log('this is a debug message');

function solution(A) {
  // write your code in JavaScript (Node.js 8.9.4)

  // Making it shorter.
  let len = A.length;

  // Definitely need to store, and initialise first value.
  let left = new Array(len);
  left[0] = A[0];

  // Same as above, but initialise for last value.
  let right = new Array(len);
  right[len - 1] = A[len - 1];

  let trackLowest = Number.MAX_SAFE_INTEGER;

  // One shot calculate for both at any element (from 'outwards' 'in').
  // Note there is 2 elements at least, and we already preset the first
  // element, so we start and build from index 1.
  for (let i = 1; i < len; ++i) {
    left[i] = left[i - 1] + A[i];
    right[len - 1 - i] = right[len - i] + A[len - 1 - i];
  }

  // Once the above is done, it's time to calculate the difference.
  // If I am at index 0, then I want sum of index 0 AND left, and sum of index
  // 1 and right (note not index 0 also).
  // We stop before len - 1 because that's the rules and the sum of right will
  // have been out of bounds if we want difference for last index, isn't it?
  for (let i = 0; i < len - 1; ++i) {
    let smallestDiff = Math.abs(left[i] - right[i + 1]);
    if (smallestDiff < trackLowest) {
      trackLowest = smallestDiff;
    }
  }

  return trackLowest;
}

大致总结一下,您同时在左侧和右侧进行循环。 一旦完成,就得到区别,就是这样。 O(n)复杂度。

答案 6 :(得分:0)

您实际上可以使用C#中的一个循环来做到这一点。

添加Linq:

 public int solution(int[] A)
    {

        // write your code in C# 6.0 with .NET 4.5 (Mono)
            long sum = A.Sum(p => (long)p);
            int val1 = Convert.ToInt32(A.GetValue(0));
            int val2 = Convert.ToInt32(sum - val1);
            int result = Math.Abs(val1 - val2);
            for (int i = 1; i < A.Length-1; i++)
            {
                val1 += Convert.ToInt32(A.GetValue(i));
                val2 -= Convert.ToInt32(A.GetValue(i));
                if (result > Math.Abs(val1 - val2))
                {
                    result = Math.Abs(val1 - val2);
                }
            }


        return result;
    }

答案 7 :(得分:0)

Ruby 100%

def solution(a)
  left = a.inject(:+)
  right = 0
  a[0...-1].inject(Float::INFINITY) do |min, el|
    left -=el
    right += el
    candidate = (right-left).abs
    min < candidate ? min : candidate 
  end
end

答案 8 :(得分:0)

Swift 4中的TapeEquilibrium

public func solution(_ A : inout [Int]) -> Int {
    let P = 1
    var splitIndex = P
    var firstPartSum = A[splitIndex - 1]
    var secondPartSum = Array(A[splitIndex..<A.count]).reduce(0, +)
    var minimalDifference =  abs(firstPartSum - secondPartSum)

    if minimalDifference == 0 {
        return minimalDifference
    }

    splitIndex += 1

    while splitIndex < A.count {
        firstPartSum += A[splitIndex - 1]
        secondPartSum -= A[splitIndex - 1]

        let dif = abs(firstPartSum - secondPartSum)

        if dif == 0 {
            return dif
        }

        if dif < minimalDifference {
            minimalDifference = dif
        }

        splitIndex += 1
    }

    return minimalDifference
}

答案 9 :(得分:0)

这是我的Java, //得到91%,因为“int totalRight = (Arrays.stream(A).sum() - A[0]);”加载时间太长

int totalLeft = A[0];
    int totalRight = (Arrays.stream(A).sum() - A[0]);
    //int afterMinus = 0;
    int min = 0;

    min = Math.abs(totalLeft - totalRight);

    for(int i=1; i<(A.length-1); i++) {
        //for(int j=A.length; j>0; j--) {
        totalLeft += A[i];
        totalRight -= A[i];
        //System.out.println("totalLeft = "+ totalLeft);
        //System.out.println("totalRight = "+ totalRight);
        if(Math.abs(totalLeft - totalRight) < min) {
            //System.out.println("min = "+ min);
            min = Math.abs(totalLeft - totalRight);
        }
    }

    return min;

//获得100%,因为将“int totalRight = (Arrays.stream(A).sum() - A[0]);”更改为for循环

//int totalSum = Arrays.stream(A).sum();
    int totalLeft = A[0];
    int totalRight = 0;
    //int afterMinus = 0;
    int min = 0;

    for(int i=1; i<A.length; i++) {
        totalRight += A[i];
    }
    min = Math.abs(totalLeft - totalRight);

    for(int i=1; i<(A.length-1); i++) {
        //for(int j=A.length; j>0; j--) {
        totalLeft += A[i];
        totalRight -= A[i];
        //System.out.println("totalLeft = "+ totalLeft);
        //System.out.println("totalRight = "+ totalRight);
        if(Math.abs(totalLeft - totalRight) < min) {
            //System.out.println("min = "+ min);
            min = Math.abs(totalLeft - totalRight);
        }
    }

    return min;

嗯,从91%到100%,感谢@sebadagostino冲浪了近2个小时的逻辑和提示。

答案 10 :(得分:0)

以下是我获得100%的解决方案。正如你们大多数人所做的那样,我首先得到了数组的总和,然后在添加左右部分然后获取它们的绝对值并将结果放入地图然后检查地图中的最小值时进行处理。

    int totalLeft = 0;
    int totalRight = 0;
    int total = 0;
    int result = 0;
    Map<Integer, Integer> map = new HashMap<Integer, Integer>();

    for (int i = 0; i < A.length; i++) {
        total += A[i];
    }

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

        totalRight = total - (A[i] + totalLeft);
        totalLeft += A[i];

        result = Math.abs(totalLeft - totalRight);

        map.put(i, result);


    }


    return Collections.min(map.values());

答案 11 :(得分:0)

这是我的C#解决方案。得分100%

        if (A == null || A.Length == 0)
        {
            return 0;
        }

        int d1 = 0;
        int d2 = A.Sum();
        int p = 1;
        int x = int.MaxValue;

        // Replaced using A.sum();
        //for (int i=0; i < A.Length; i++)
        //{
        //        d2 += A[i];
        //}

        for (int j = 0; j < A.Length; j++)
        {
            if (j < p)
            {
                d1 += A[j];
            }

            int ad = Math.Abs(d1 - (d2 - d1));

            x = Math.Min(x, ad);

            if (p == A.Length -1) { break; }
            p++;
        }

        return x;

答案 12 :(得分:0)

我使用Java 8分享我的100%解决方案。

public class TapeEquilibrium {

public int tapeEquilibrium(int[] A) {
    final int N = A.length;
    long minimalSum = (int) A[0];

    int[] rightSide = Arrays.copyOfRange(A, 1, N);
    long maximalSum = IntStream.of(rightSide).sum();

    int minimalDifference = (int) Math.abs(maximalSum - minimalSum);
    for (int i = 1; i < N; i++) {
        int difference = (int) Math.abs(maximalSum - minimalSum);
        minimalDifference = difference < minimalDifference ? difference : minimalDifference;
        minimalSum += A[i];
        maximalSum -= A[i];
    }
    return minimalDifference;
}

}

答案 13 :(得分:0)

    long sumofall = 0, leftsideSum = A[0], rightsidesum=0;
    int x,LR = 0;
    ArrayList listResult = new ArrayList();
    for(x=0;x<A.Length;x++)
    {
        sumofall+= A[x];
    }

    for(x=1;x<A.Length;x++)
    {
        rightsidesum = sumofall-leftsideSum;
        LR = (int)(rightsidesum - leftsideSum);
        if(LR < 0)
        {
            LR=-LR;
        }
        listResult.Add(LR);
        leftsideSum+=A[x];
    }
    listResult.Sort();
    return Convert.ToInt32(listResult[0].ToString());
}

答案 14 :(得分:0)

试试这个:

Class Solution {

    public int solution(int[] A) {

        int sum1 = 0;
        int sum2 = 0;
        int sum3 = 0;
        int len = A.length;
        int min = 1 ;

        for(int i=0; i<len; i++){
                sum2 += A[i];
        }

        for(int i=0; i< len-1 ; i++){

            sum1 += A[i];
            sum3 = sum2-sum1;

            if( min > Math.abs(sum1- sum3)){
                min = Math.abs( sum1 - sum3);
            }

        }

        return min;
    }

}

答案 15 :(得分:0)

这是我的100%正确性的解决方案&amp;性能

int solution(int A[], int N) 
{
    int sum,i;
    sum=0;
    for(i=0;i<N;i++)
    {
        sum+=A[i];
        A[i]=sum;
    }

    int min_diff=abs(sum-A[0]*2);
    for(i=0;i<N-1;i++)
    {
        int tmp;
        tmp=abs(sum-A[i]*2);

        if(tmp<min_diff)
            min_diff=tmp;
    }

    return min_diff;
}

答案 16 :(得分:0)

这是我的implementation使用Java 8 IntStream来简化总和过程...
100%正确,100%表现。

import java.util.stream.IntStream;

public class TapeEquilibrium {

    public static int diffIndex( int[] A ) {

        long lower = 0, diff = 0, higher = IntStream.of( A ).asLongStream().sum(), minDiff = Integer.MAX_VALUE;
        for(int i = 0; i < A.length-1; i++) {
            lower += A[i];
            higher -= A[i];
            diff = Math.abs( higher - lower);
            if( diff < minDiff  ) {
                minDiff = diff;
            }
        }
        return (int) minDiff;
    }


    public static void main( String[] args ) {

        int[] A = { 3, 1, 2, 4, 3 };
        System.out.println( diffIndex( A ) );

    }
}    

答案 17 :(得分:0)

对于%83的结果,问题是它说“将这个磁带分成两个非空的部分”。因此,如果您拆分A [0],您的第一个数组将为空。所以你应该从A [1]开始。

答案 18 :(得分:0)

..或者甚至更短一点来获得100%

public int solution(int[] A) {
    int sumMin = A[0];
    int sumMax = 0;

    for (int i = 1; i < A.length; i++) {
        sumMax += A[i];
    }

    int minDif = Math.abs(sumMin - sumMax);
    for (int i = 1; i < A.length - 1; i++) {
        sumMin += A[i];
        sumMax -= A[i];
        minDif = Math.min(minDif, Math.abs(sumMin - sumMax));
    }

    return minDif;
}

答案 19 :(得分:0)

C中的TapeEquilibrium

int solution(int A[], int N) {
    // write your code in C90
    long int s_r=0,s_l=A[0],sum=A[0];
    int i,min=11111111,r;

    for(i=1;i<N;i++)
        sum+=A[i];

    for(i=1;i<N;i++)
    {
        s_r=sum-s_l;
        r=(int)(s_l-s_r);
        if(r<0) r=-r;
        if(min>r)min=r;
        if(min==0)break;
        s_l=sum-s_r+A[i];
    } 
    return min;
}

答案 20 :(得分:0)

user699681的反例:A = {0, 1, 2, -5, 2}, 对于Ism:A = {1, -1}