简体   繁体   English

减少算法的时间复杂度

[英]Reducing time complexity of an algorithm

This is a task taken from codility, which requires O(n) complexity. 这是一项从Codility中提取的任务,需要O(n)复杂性。 Although I've solved the task that it gives correct results, the time complexity is O(n*n). 尽管我已经解决了给出正确结果的任务,但是时间复杂度是O(n * n)。 Would appreciate any help in explaining how to reduce that complexity to O(n). 希望对解释如何将复杂度降低到O(n)有帮助。

Task description: 任务描述:

A non-empty zero-indexed array A consisting of N integers is given. 给出了一个由N个整数组成的非空零索引数组A。 Array A represents numbers on a tape. 数组A代表磁带上的数字。

Any integer P, such that 0 < P < N, splits this tape into two non-empty parts: A[0], A[1], ..., A[P − 1] and A[P], A[P + 1], ..., A[N − 1]. 任何整数P,例如0 <P <N,都会将此磁带分割为两个非空部分:A [0],A [1],...,A [P − 1]和A [P],A [ P + 1],...,A [N − 1]。

The difference between the two parts is the value of: |(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])|

In other words, it is the absolute difference between the sum of the first part and the sum of the second part. 换句话说,它是第一部分之和与第二部分之和之间的绝对差。

For example, consider array A such that: 例如,考虑数组A这样:

A[0] = 3 A[1] = 1 A[2] = 2 A[3] = 4 A[4] = 3 A [0] = 3 A [1] = 1 A [2] = 2 A [3] = 4 A [4] = 3

We can split this tape in four places: 我们可以将此磁带分成四个位置:

  P = 1, difference = |3 − 10| = 7 P = 2, difference = |4 − 9| = 5 P = 3, difference = |6 − 7| = 1 P = 4, difference = |10 − 3| = 7 

Write a function: 编写一个函数:

 int solution(vector<int> &A); 

that, given a non-empty zero-indexed array A of N integers, returns the minimal difference that can be achieved. 在给定N个整数的非空零索引数组A的情况下,该函数返回可以实现的最小差异。

For example, given: 例如,给定:

A[0] = 3 A[1] = 1 A[2] = 2 A[3] = 4 A[4] = 3 A [0] = 3 A [1] = 1 A [2] = 2 A [3] = 4 A [4] = 3

the function should return 1, as explained above. 该函数应返回1,如上所述。

Assume that: 假使,假设:

  N is an integer within the range [2..100,000]; each element of array A is an integer within the range [−1,000..1,000]. 

Complexity: 复杂:

  expected worst-case time complexity is O(N); expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments). 

Elements of input arrays can be modified. 输入数组的元素可以修改。

My solution:  
int solution(vector<int>& A)
{
    // write your code in C++11
    int result = std::numeric_limits<int>::max();
    int part_1 = 0;
    int part_2 = 0;
    for (auto beg = A.cbegin(), end = A.cend(); beg != prev(end); ++beg)
    { 
        part_1 = accumulate(A.cbegin(),beg + 1,0);
        part_2 = accumulate(beg + 1,end,0);
        int current_result = abs(part_1 - part_2);
        if (current_result < result)
        {
            result = current_result;
        }

    }

    return result;
}

Let S[i] = sum of the first i elements . S[i] = sum of the first i elements You can compute this with a single for loop: 您可以使用单个for循环进行计算:

S[0] = A[0]
for (int i = 1; i < n; ++i)
  S[i] = S[i - 1] + A[i]

Then, for each index 0 < i < n , the sum up until i - 1 is simply S[i - 1] . 然后,对于每个索引0 < i < n ,直到i - 1的总和就是S[i - 1] The sum from i to the end of the array is S[n - 1] - S[i - 1] : i到数组末尾的总和为S[n - 1] - S[i - 1]

S[n - 1] = A[0] + ... + A[n - 1]
S[i - 1] = A[0] + ... + A[i - 1]

0 < i < n

S[n - 1] - S[i - 1] =  A[0] + ... + A[i - 1] + A[i] + ... + A[n - 1] -
                      (A[0] + ... + A[i - 1])
                    = A[i] + ... + A[n - 1]

After computing S , run another loop and check the differences between the two sums, which are computed in O(1) like I described: 在计算S ,运行另一个循环并检查两个和之间的差,就像我描述的那样,它们在O(1)进行计算:

for (int i = 1; i < n; ++i)
{
  sum_left = S[i - 1]
  sum_right = S[n - 1] - S[i - 1]

  // see if |sum_left - sum_right| is better than what you have so far
}

The time complexity is O(n) because you only run two for loops in which you only do O(1) operations at each iteration. 时间复杂度为O(n)因为您只运行两个for循环,在每次循环中您只执行O(1)操作。 The memory complexity is O(n) because you have to store S , which is the same size as your input. 内存复杂度为O(n)因为必须存储S ,它的大小与输入的大小相同。

Declaring S as int[n] should be fine judging by the assumptions we're allowed to make. 从我们可以做的假设来看,将S声明为int[n]应该很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM