用于比较排序数组的算法

时间:2013-08-21 08:15:28

标签: arrays algorithm sorting

我有两个排序的数组。我需要找出两者是否不同。

这些数组的元素属于特定范围

更多一个元素可能会有所不同。

阵列可以有不同的大小。在这种情况下,我应该能够指出差异

一个粗略的例子:

输入:

array1: 1 2 4 5 8 9 12
array2: 1 4 8 10 12 13 14

这里的范围是1-15。

最佳比较算法是什么?

我应该能够指出差异和相似之处,例如: 4是两个,第二个数组中缺少5个。

我的解决方案:

  1. 两个指针,用于跟踪数组的索引。

  2. 将它们指向数组的开头。

  3. 开始比较前两个元素。

  4. 如果两者相等 - >转到下一个。
    其他

    1. 找到数组中两个元素中最大的一个。比如array1有更大的元素。

    2. 二元搜索另一个数组中的元素。(array2) - >该数组中该元素的pos表示pos

    3. 弃掉数组的元素直到pos。

  5. 增量指针。 丢弃这个部分的数组直到这个指针。重复。

  6. 这具有n log n的复杂性(远低于平均值,这是当您必须搜索每个元素时)。

7 个答案:

答案 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种可能性:

  • 如果array3 [i] == 1 //那么元素i在array1中但不在array2中
  • 如果array3 [i] == -1 //则元素i在array2中但不在array1
  • 如果array3 [i] == 0 //那么元素i在两个数组中或者都不存在。

时间复杂度 - O(范围),内存复杂度 - O(范围)。如果范围不是从0开始,那么您可以为每个索引创建一个偏移量。

示例:

  • 范围:1-15
  • array1:1 2 4 5 8 9 12
  • array2:1 4 8 10 12 13 14

在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个   列表/套)

  •   
  • 您现在可以拥有三种情况之一

         
        
    1. p1的值等于p2 :    将值添加到 v array1: 1 2 4 5 8 9 12 v array2: 1 4 8 10 12 13 14 数组并增加

    2.   
    3. p1的值小于p2 :    将p1的值添加到in both数组中,并仅增加p1

    4.   
    5. p1的值大于p2 :    将p2的值添加到only in array1数组中,并仅增加p2

    6.   
  •   
  • 在这些条件上循环,直到你到达阵列的一端(或两者都是这样)。然后添加任何剩余的项目   另一个列表是它的only in array2列表。

  •   

此算法仅触及每个项目一次,因此它应为O( n )。希望这有帮助

相关问题