Codility - 使用Python进行磁带均衡训练

时间:2017-12-30 01:28:56

标签: python

  

给出了由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])|换句话说,它是第一部分之和与第二部分之和的绝对差值。

def solution(A):
N = len(A)
my_list = []
for i in range(1, N):
    first_tape = sum(A[:i - 1]) + A[i]
    second_tape = sum(A[i - 1:]) + A[i]
    difference = abs(first_tape - second_tape)
    my_list.append(difference)
print(min(my_list))
return min(my_list)

我的解决方案在正确性方面获得100%,在性能方面获得0%。 我认为它应该是O(N),但我的时间复杂度是O(N * N)。 请问有人可以给我建议吗?

9 个答案:

答案 0 :(得分:4)

您可以将代码更改为以下类似内容,以使其具有O(N)的复杂性。

def solution(A):          
    s = sum(A)
    m = float('inf')
    left_sum = 0
    for i in A[:-1]:
        left_sum += i
        m = min(abs(s - 2*left_sum), m)
    return m

答案 1 :(得分:2)

我的Java代码 O(N)

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

   int sum = 0;

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



  int  minSum = 100000;
  int  tempSum = 0;
  int previousSum = 0;
   for(int i = 0; i<arr.length-1; i++){

       previousSum = previousSum + arr[i];

      tempSum = Math.abs(previousSum - (sum - previousSum));

      if(minSum > tempSum){
          minSum = tempSum;
      }


   }

   return minSum;
}

}

答案 2 :(得分:1)

@darkvalance所写的功能方法,但有注释:

from itertools import accumulate

def solution(A):
    array_sum = sum(A)  # saving sum of all elements to have an O(n) complexity

    # accumulate returns accumulated sums
    # e.g. for input: [3, 1, 2, 4] it returns: [3, 4, 6, 10]
    # we are passing a copy of the array without the last element
    # including the last element doesn't make sense, becuase
    # accumulate[A][-1] == array_sum
    accumulated_list = accumulate(A[:-1])

    return min([abs(2*x - array_sum) for x in accumulated_list])

答案 3 :(得分:1)

当前,您正在first_tapesecond_tape中一次又一次地计算总和。您需要做的是存储总和,并使用差值计算总和。所以如果您的数组为[1,2,3,4],则总和为10。假设您的first_tape的大小为1,换句话说,您的first_tape的大小为[1],因此第一卷磁带的总和为1。那么剩余的第二盘磁带的总和就是

`total sum - first_tape sum`

和不同的是

first_tape sum - (total sum - first_tape sum)

您可以执行以下操作来计算同一循环内的first_tape和:

previous sum += i (where i is the current array element)

所以解决方案是N的顺序。

答案 4 :(得分:0)

要回答您的问题-它是O(n * n),因为sum()函数的时间复杂度是O(n),并且您在带有for元素的N循环内调用它,也是O(N)。

因此,算法的时间复杂度为O(N * n)

答案 5 :(得分:0)

我的python代码O(N)

def solution(A):
    # write your code in Python 3.6
    mini = float('inf')
    check = A[0]
    total = sum(A)-check
    for i in range(1, len(A)):
        diff = abs(check-total)
        total -= A[i]
        check += A[i]
        if diff < mini:
            mini = diff
    return mini

答案 6 :(得分:0)

函数方法O(N)。累积提供列表的累积运行总和。我们可以使用列表的总和以及每个点的累加总和来计算两个数组之间的差。

from itertools import accumulate

def solution(A):
    s = sum(A)
    l = list(accumulate(A[:-1]))
    return min([abs(2*x - s) for x in l])

答案 7 :(得分:0)

在这里,我还添加了检查数组元素为0的时间

def MinimialDiff(A):

    if len(A) == 2:
        return abs(A[0]-A[1])

    tot_sum = sum(A)
    min_value = float('inf')
    left_sum = 0
    for x in range(0,len(A)-1):
        if A[x] == 0:
            continue
        left_sum += A[x]
        temp = abs(2*left_sum-tot_sum)
        min_value = min(min_value,temp)

    return min_value

答案 8 :(得分:0)

def solution(A):
   res = []
   left_sum = 0
   right_sum = sum(A)
   for i in range(0, len(A)-1):
       left_sum += A[i]
       right_sum = right_sum - A[i]
       res.append(abs(right_sum-left_sum))
   return min(res)