【问题标题】:Codility: MaxZeroProduct - complexity issuesCodility:MaxZeroProduct - 复杂性问题
【发布时间】:2018-11-30 19:08:05
【问题描述】:

我的解决方案的正确性为 100%,但性能为 0%。 我只是不知道如何最小化时间复杂度。

问题:

写一个函数:

int solution(int A[], int N);

给定一个包含 N 个正整数的数组,返回通过将数组中的三个不同元素相乘而获得的数字的尾随零的最大数量。如果数字在数组中的不同位置,则认为它们是不同的。

例如,给定 A = [7, 15, 6, 20, 5, 10],该函数应返回 3(您可以通过取数字 15、20 和 10 或 20、5 的乘积来获得三个尾随零和 10)。

再举一个例子,给定 A = [25, 10, 25, 10, 32],该函数应该返回 4(您可以通过取数字 25、25 和 32 的乘积来获得四个尾随零)。

假设:

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

复杂性:

  • 预计最坏情况时间复杂度为 O(N*log(max(A)));
  • 预计最坏情况下的空间复杂度为 O(N)(不包括输入参数所需的存储空间)。

解决方案:

想法:

  1. 将每个元素分解为 5 和 2 对
  2. 每个 3 对组合成一对 - 这需要 O(N^3)
  3. 找出最小坐标值最大的对
  4. 返回最小坐标值

代码:

int solution(int A[], int N) {
    int fives = 0, twos = 0, max_zeros = 0;
    int(*factors)[2] = calloc(N, sizeof(int[2])); //each item (x,y) represents the amount of 5's and 2's of the corresponding item in A

    for (int i = 0; i< N; i++) {
        factorize(A[i], &fives, &twos);
        factors[i][0] = fives;
        factors[i][1] = twos;
    }

    //O(N^3)
    for (int i = 0; i<N; i++) {
        for (int j = i + 1; j<N; j++) {
            for (int k = j + 1; k<N; k++) {
                int x = factors[i][0] + factors[j][0] + factors[k][0];
                int y = factors[i][1] + factors[j][1] + factors[k][1];
                max_zeros = max(max_zeros, min(x, y));
            }
        }
    }
    return max_zeros;
}

void factorize(int val, int* fives, int* twos) {
    int tmp = val;  
    *fives = 0, *twos = 0;

    if (val == 0) return;    
    while (val % 5 == 0) { //factors of 5
        val /= 5;
        (*fives)++; 
    }
    while (val % 2 == 0) { //factors of 2
        val /= 2;
        (*twos)++;
    }
} 

我不知道我还能如何遍历 N 大小的数组,以便在 O(N*log(max(A))) 时间内找到最佳的 3 项。

【问题讨论】:

  • 嗨,这个问题可能更适合Code review,因为它确实有效,但需要改进算法。

标签: c algorithm performance time-complexity


【解决方案1】:

由于 2^30 > 1e9 和 5^13 > 1e9,数组中有 30 * 13 = 390 对不同的因子 2 和 5 的限制,无论数组有多大。这是一个上限(实际数字是 213)。

为每一对从数组中丢弃除三个代表之外的所有代表,然后您的 O(N^3) 算法可能就足够快了。

如果仍然不够快,您可以继续应用动态规划,计算 P[i,j],即索引

【讨论】:

  • 可能他们想要别的东西,因为预期的最坏情况空间复杂度是 O(N)
  • @AlexanderAnikin 我不明白为什么这个答案不满足复杂性约束。非DP方案使用O(log N)空间,DP方案使用O((log N)^3)空间。两者都是 O(N)。
  • 问题在于答案过度满足复杂性约束。
  • 是的!有效。我尝试了非DP解决方案。根据 Codility,时间复杂度为 O(N*log(max(A))+log(max(A))**6)。谢谢!
【解决方案2】:

在现实世界中我不喜欢这种元思维,但我们仍然面临一些人为限制的人为问题......

由于空间复杂度为 O(N),我们无法承受基于初始输入的动态规划。我们甚至无法制作 N* 因子的地图。好吧,无论如何,我们可以负担得起 N*2 的地图,但我们几乎只能做到这一点。

由于时间复杂度为 O(Nlog(max(A))),我们可以允许自己分解项目并进行一些简单的单向归约。或许我们可以使用计数排序来对项目进行排序 - 它有点像 Nlog^2(max(A)) 用于 2-index 排序,但大 O 会均匀。

如果我的蜘蛛感觉是正确的,我们应该简单地从这个 counts 数组中挑选一些东西,然后用 1-run through 数组来完善它。最好是 2,然后最好是 5,然后我们可以枚举其余元素以找到最佳整体产品。这只是启发式的,但尺寸不会说谎!

只要我的 2 美分

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-25
    • 2021-03-24
    • 2017-11-28
    • 2011-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多