【问题标题】:What is the efficient way to get the diff of two arrays in C? [closed]在 C 中获取两个数组的差异的有效方法是什么? [关闭]
【发布时间】:2016-01-05 15:58:04
【问题描述】:

示例输入

Array_1 [] = { 10, 20, 30, 40, 50 };
Array_2 [] = { 30, 40, 50, 60, 70 };

样本输出

Array_1_Extras [] = { 10, 20 };
Array_2_Extras [] = { 60, 70 };

说明

  1. 输入数组未排序。

  2. 输入数组长度 - 10K。

  3. 输入数组值范围为 0 - 4095。

  4. 不应修改输入数组的顺序和值。

  5. 输出数组可以是任意顺序。

  6. 输出数组中不需要重复。

我需要一些高效的逻辑来处理这个程序。提前致谢。

【问题讨论】:

  • 数组是否已排序?它们是严格整数吗?数字有界吗?
  • 所有数字都是正数吗?他们有上限吗?改变数组顺序可以吗?
  • 任一数组的长度是否有界?
  • 叹息...你试过什么?
  • 那么,据我了解,元素不是唯一的?你如何处理两个相同的元素?

标签: c arrays algorithm


【解决方案1】:

这是一个简单的 O(N) 时间算法,有点占用空间(它也考虑了重复)。

1) 声明一个长度为零的数组C 4096
2) 迭代第一个数组A 和索引i 的每个元素increment C[A[i]]
3) 迭代第二个数组B,并为每个元素i 递减 C[B[i]]
4) 遍历Ci 的负数C[i] 表示B - A 的元素,正数表示A - B 的元素
* 并且绝对值将表示被骗数的差异,如果您有兴趣..

【讨论】:

  • 关于重复项:我认为,如果您在第一个数组中有三个 10,而在第二个数组中只有一个,则 10 不应该出现在任何一个差异中,因为数组被视为集合.您的答案会将 10 视为 A - B 的元素。
  • @MOehm 是的。这取决于问题的定义。使用您的定义,C 的元素应介于-11 之间。更新:实际上没有..第二个数组的迭代应该只是重置值..但是我们不会得到对称的结果。如果我们添加额外的检查,我们会这样做。无论如何,我相信它展示了整体想法。
  • 是的。我猜这个问题一开始就没有很好地说明。
【解决方案2】:

这是一个 O(n) 的实现:

int seen[4096];
memset(seen, 0, sizeof(seen));
int a[10000], b[10000];
size_t aSize, bSize;
... // Fill a and b
for (size_t i = 0 ; i != aSize ; i++) {
    seen[a[i]] |= 1;
}
for (size_t i = 0 ; i != bSize ; i++) {
    seen[b[i]] |= 2;
}
size_t j = 0;
for (size_t i = 0 ; i != aSize ; i++) {
    if (seen[a[i]] == 1) {
        a[j++] = a[i];
    }
}
aSize = j;
j = 0;
for (size_t i = 0 ; i != bSize ; i++) {
    if (seen[b[i]] == 2) {
        b[j++] = b[i];
    }
}
bSize = j;

这种方法会删除 a 中同样在 b 中的所有数字,无论它们的数量是多少。它还保留重复项。例如,如果输入是这样的

a = [10, 10, 10, 20, 20, 20, 30 , 40]
b = [10, 30, 40, 40, 40, 40, 50]

输出将是

a = [20, 20, 20]
b = [50]

【讨论】:

    【解决方案3】:

    对于大小为 10000 的输入数组,您很有可能能够通过通用算法的渐近复杂度来判断。

    简单的算法是遍历一个数组,扫描另一个数组以查找每个元素的外观,然后反转角色并再次执行此操作。如果较长数组的大小与较短数组的大小之比为O(1),则此方法的成本为O(n2)

    您可以通过创建输入数组 (O(n)) 的副本、对它们进行排序 (O(n log n)) 并对排序后的数组执行一次联合线性扫描(类似于合并步骤)来以 O(n log n) 的成本解决问题归并排序 (O(n))。

    鉴于输入数组中的值是从一个相对较小的范围中提取的,因此考虑整体为O(n) 的解决方案是合理的:

    1. 为每个可能的输入数组值创建一个包含一个 2 位或更宽位域元素的数组
    2. 扫描第一个输入数组;为每个值设置对应于该值的位域的零位
    3. 扫描第二个输入数组;为每个值设置与该值对应的位域之一
    4. 扫描位域数组:元素会告诉您相应的输入值是出现在两个输入数组中、恰好出现在一个数组中,还是两者都不出现。

    【讨论】:

      【解决方案4】:
      1. 对数组进行排序(如果无法更改原件,则为副本)
      2. 递归地遍历它们,直到它们完成

      对于每个递归,取每个数组的第一个元素。

      一个。如果它们不同,则将较小的添加到 array_1_extrasarray_2_extras 并使用该元素推进数组
      湾。如果它们相等,注意重复并推进两个数组

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多