我有两个排序的数组。我需要找出两者是否不同。
这些数组的元素属于特定范围。
更多一个元素可能会有所不同。
阵列可以有不同的大小。在这种情况下,我应该能够指出差异
一个粗略的例子:
输入:
array1: 1 2 4 5 8 9 12
array2: 1 4 8 10 12 13 14
这里的范围是1-15。
最佳比较算法是什么?
我应该能够指出差异和相似之处,例如: 4是两个,第二个数组中缺少5个。
我的解决方案:
两个指针,用于跟踪数组的索引。
将它们指向数组的开头。
开始比较前两个元素。
如果两者相等 - >转到下一个。
其他
找到数组中两个元素中最大的一个。比如array1有更大的元素。
二元搜索另一个数组中的元素。(array2) - >该数组中该元素的pos表示pos
弃掉数组的元素直到pos。
增量指针。 丢弃这个部分的数组直到这个指针。重复。
这具有n log n
的复杂性(远低于平均值,这是当您必须搜索每个元素时)。
答案 0 :(得分:2)
(4。) - 而不是二元搜索进行线性搜索。
整体复杂性:O(n) - 当你完全访问每个项目时。
答案 1 :(得分:1)
完全未经测试(并且在有重复项时效果不佳):
var same = new List<int>();
var inAonly = new List<int>();
var inBonly = new List<int>();
int b = 0;
int a = 0;
//first look at all the elements until one of the lists run out of elements
for(; a < inputa.Count && b < inputb.Count;) {
//if element is the same, then add to same
//and the problem with duplicates is found here, if a contains two "1", but b only contains one, then same will report a single "1", but inAonly will also contain a "1"
if (inputa[a] == inputb[b]){
same.Add(inputa[a]);
a++;
b++;
}
//otherwise, we check if a < b, if that is the case, we know that a only exists in a, otherwise it must only exist in b.
else if (inputa[a] < inputb[b])
{
inAonly.Add(inputa[a]);
a++
} else {
inBonly.Add(inputb[b]);
b++
}
}
//add the rest of the elements if one array is longer than the other
for(; a < inputa.Count;a++)
inAonly.Add(inputa[a]);
for(; b < inputb.Count;b++)
inBonly.Add(inputb[b]);
答案 2 :(得分:0)
因为两个数组都已排序。最好是使用线性搜索。
答案 3 :(得分:0)
如果数组是内存块 - 您可能已经使用malloc分配的内容,则可以通过将数组转换为32位或64位整数来加速比较。这样,您就可以将一些数组元素与单个== test进行比较。
此外,如果你知道数组有特定数量的元素,那么将循环展开到,例如,8 if语句会更快。它将保存比较并在循环结束时跳转。
答案 4 :(得分:0)
@Alvin 你的算法似乎适合我。因为你必须指出相似之处和不同之处,所以你必须在每一个差异的情况下进行搜索。
我认为复杂性将优于nlgn,因为您不必在完整数组中搜索每个差异。这是因为你也将元素丢弃到pos。
答案 5 :(得分:0)
如果array1和array2具有相同的大小,则迭代它们并逐个元素地比较它们。当找到第一个差异时=>数组是不同的。如果到达数组的末尾,则意味着它们是相等的。复杂度在时间上是O(数组的长度),在内存中是O(1)。
如果array1和array2具有不同的大小,则分配另一个具有size的数组 - 元素的范围,并用零(array3)初始化它。对于array3中的每个元素,array3中的增量元素如下所示:array3 [array1 [i]] ++
之后以相同的方式迭代array2,但递减:array3 [array2 [i]] -
之后,对于array3中的每个元素,您有3种可能性:
时间复杂度 - O(范围),内存复杂度 - O(范围)。如果范围不是从0开始,那么您可以为每个索引创建一个偏移量。
示例:
在step1之后,array3将如下所示:
index: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
value: 1 1 0 1 1 0 0 1 1 0 0 1 0 0 0
在step2之后,array3将如下所示:
index: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
value: 0 1 0 0 1 0 0 0 1 -1 0 0 -1 -1 0
答案 6 :(得分:0)
您的方法正确无误,但搜索不是必需的。 (参见实际算法的底部)
从指向开头的2个指针开始:
v
array1: 1 2 4 5 8 9 12
v
array2: 1 4 8 10 12 13 14
(就像你一样)如果元素相同,则将它们添加到"In-Both"
设置然后增加两个指针,所以现在我们有:
v
array1: 1 2 4 5 8 9 12
v
array2: 1 4 8 10 12 13 14
所以现在我们遇到了不同的元素,而不是在这里搜索,我们可以利用这样一个事实:我们知道事实上指针不在array2
的2过去,所以我们添加{{ 1}}到我们的2
集。并仅增加 "Only_in_array1"
指针。所以我们最终得到:
array1
我们最终得到了匹配,所以我们将{4}添加到 v
array1: 1 2 4 5 8 9 12
v
array2: 1 4 8 10 12 13 14
并增加两个指针:
"In-Both"
如果你继续这种模式,你最终会得到:
v
array1: 1 2 4 5 8 9 12
v
array2: 1 4 8 10 12 13 14
当第一个指针从数组中掉落时,您将知道第二个(更长)数组中的其余元素不在第一个中。
要概括算法:
从两个数组开头的2个指针开始(初始化和数据结构,你想要保存信息:我用过3个 列表/套)
您现在可以拥有三种情况之一
p1的值等于p2 : 将值添加到
v array1: 1 2 4 5 8 9 12 v array2: 1 4 8 10 12 13 14
数组并增加p1的值小于p2 : 将p1的值添加到
in both
数组中,并仅增加p1p1的值大于p2 : 将p2的值添加到
only in array1
数组中,并仅增加p2在这些条件上循环,直到你到达阵列的一端(或两者都是这样)。然后添加任何剩余的项目 另一个列表是它的
only in array2
列表。
此算法仅触及每个项目一次,因此它应为O( n )。希望这有帮助