【问题标题】:Comparison of all array elements - C algorithm所有数组元素的比较 - C 算法
【发布时间】:2013-03-18 21:10:52
【问题描述】:

我有一个矩阵 m * n 并且对于每一行,我需要比较它们之间的所有元素。 对于我找到的每一对,我都会调用一个函数来执行一些计算。

例子:

my_array -> {1, 2, 3, 4, 5, ...}

I take 1 and I have: (1,2)(1,3)(1,4)(1,5)
I take 2 and I have: (2,1)(2,3)(2,4)(2,5)
and so on

我用 C 写了这个:

for (i=0; i<array_length; i++) {
    for (k=0; k<array_length; k++) {
        if (i==k) continue;

           //Do something
        }
    }
}

我想知道是否可以使用复杂度较低的算法。

【问题讨论】:

  • 在不知道具体计算的情况下,无法判断可以优化什么。
  • 那么,你真的有一个矩阵,还是你只是在谈论小自然数的排列?
  • 有 n^2 对,所以你不能比 n^2 做得更好...

标签: c arrays algorithm matrix comparison


【解决方案1】:

不,它的定义是 O(n^2) [ 在这里解释太长了,但相信我 (-: ]
但是您可以将迭代次数减少一半:

for (i=0; i<array_length; i++) {
    for (k=i+1; k<array_length; k++) { // <-- no need to check the values before "i"
           //Do something
           //If the order of i and k make a different then here you should:
           //'Do something' for (i,k) and 'Do something' for (k,i)
        }
    }
}

【讨论】:

  • 您的归约假设 x 操作 y 与 y 操作 x 相同,换句话说,操作是可交换的。如果不是,你不能那样减少它。
  • 是的,我不能使用它,因为它不是可交换的
  • @wich - 我在“做某事”中添加了评论。你可以在内部代码中做 (x,y) and (y,x) 在同一次迭代中。
  • 如果你打算从i+1开始k,你可以放弃if。
  • 重复元素与问题无关。 i 和 k 是索引,if永远不会为真。
【解决方案2】:

您可能会做几件事,但哪些是可能的,哪些不取决于数组性质和您应用的公式。总体复杂度可能会保持不变,甚至会增加,即使计算速度可以更快,除非公式的复杂度依赖于其参数,在这种情况下,可以实现复杂度的降低。

此外,从 AO(N^a) 到 BO(N^b) with b > a(更高的复杂度)仍然值得追求,对于某个范围的 N,如果 B 是比 A 小很多。

不分先后:

  • 如果矩阵有多个重复项,使用缓存功能可以很方便:

    结果函数(arg1,arg2){ int i = 索引(arg1,arg2); // 根据值,它可能是 // 类似 arg1*(MAX_ARG2+1) + arg2; if (!stored[i]) { // 存储并分配和初始化值 // 在其他地方 - 或者在这个函数中使用 // 静态标志。 存储[i] = 1; 值[i] = true_function(arg1, arg2); } 返回值[i]; }

    然后,您的内存开销与不同对的数量成正比 的可用值。调用开销可能是 O(|arg1|*|arg2|),但在某些情况下 (例如true_function() 很昂贵)节省的费用将抵消增加的复杂性。

    • 将公式切成小块(对于每个公式都不可能)并将其表示为:

      F(x,y) = G(x) 运算 H(y) 运算 J(x,y)

    然后,您可以执行 O(max(M,N)) 循环预先计算 G[] 和 H[]。这也有 O(M+N) 的内存成本。仅当 F 和 J 之间的计算开销差异显着时才方便。或者你可以这样做:

    for (i in 0..N) {
        g = G(array[i]);
        for (j in 0..N) {
            if (i != j) {
                result = f(array[i], array[j], g);
            }
        }
    }
    

    这将一些复杂性从 O(N^2) 降低到 O(N)。

    • 如果 G() 或 H() 可用于缓存(参数范围有限,函数昂贵),则前两种技术可以串联使用。

    • 找到将 F(a, b) 与 F(a+c, b+d) 联系起来的“法则”。然后,您可以更有效地运行缓存算法,重用相同的计算。这将一些复杂性从 O(N^2) 转移到 O(N) 甚至 O(log N),因此虽然总成本仍然是二次方,但它的增长要慢得多,并且 N 的更高界限变得实用。如果 F 本身的复杂度比 (a,b) 中的常数高,这也可能会降低这个复杂度(作为一个极端的例子,假设 F 在 a 和/或 b 中是迭代的)。

【讨论】:

    【解决方案3】:

    不,只有包含数组内容的知识以及优化算法的操作语义,才能降低计算复杂度。

    【讨论】:

    • 因为 OP 必须将每个元素与其他元素进行比较,并且存在 mXn 个元素,因此存在 mXn 个比较,因此不存在提高复杂性的问题。
    • @fayyazkl 取决于函数的实际目标是什么,可能不需要所有这些比较。
    • 这是一个固定的数学公式(对不起,我不能发布内容......)。我存储从 0 到 250 的矩阵值或从 A 到 C 的字符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-16
    • 2016-03-25
    相关资源
    最近更新 更多