在C中获取两个数组的差异的有效方法是什么?

时间:2016-01-05 15:58:05

标签: c arrays algorithm

示例输入

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. 输出数组中不需要重复。

  7. 我需要一些时间有效的逻辑来实现这个程序。提前致谢。

4 个答案:

答案 0 :(得分:5)

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

1)声明一个长度为C的零的数组4096 2)迭代第一个数组A,并为索引的每个元素i 增量 C[A[i]]
3)迭代第二个数组B,并为每个元素i 递减 C[B[i]]
4)迭代Ci的否定C[i]将表示B - A的元素,正数的元素将表示A - B的元素 *如果您感兴趣,绝对值将表示欺骗号码的差异。

答案 1 :(得分:1)

这是一个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]

答案 2 :(得分:0)

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

天真算法是迭代一个数组,扫描另一个数组的外观,然后反转角色并再次执行。如果较长数组的大小与较短数组的大小之比为O(1),则此方法的成本受O(n 2 {{的限制1}}。

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

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

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

答案 3 :(得分:0)

  1. 对数组进行排序(如果无法更改原文,则为副本)
  2. 递归地走他们,直到他们完成
  3. 对于每次递归,取每个数组的第一个元素。

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