如何有效地确定两个列表是否包含以相同方式排序的元素?

时间:2010-10-23 20:03:07

标签: algorithm sorting set

我有两个相同元素类型的有序列表,每个列表每个值最多只有一个元素(比如整数和唯一数字),但是没有限制(一个可能是另一个的子集,它们可能是完全分离,或分享一些元素,但不分享其他元素。)

如何有效地确定A是否以不同于B的方式订购任何两个项目?例如,如果A具有项目1,2,10和B项目2,10,1,则该属性将不会保持为A列出1之前的10但B将其列在10之后.1,2,10 vs 2,10 ,5完全有效,但是A根本没有提到5,我不能依赖两个列表共享的任何给定的排序规则。

3 个答案:

答案 0 :(得分:4)

您可以按如下方式获得O(n)。首先,使用散列找到两组的交集。其次,如果你只考虑交叉点的元素,测试A和B是否相同。

答案 1 :(得分:0)

我的方法是首先制作AB的已排序副本,这些副本还会记录原始列表中元素的位置:

for i in 1 .. length(A):
    Apos[i] = (A, i)
sortedApos = sort(Apos[] by first element of each pair)

for i in 1 .. length(B):
    Bpos[i] = (B, i)
sortedBpos = sort(Bpos[] by first element of each pair)

现在使用标准列表合并找到这些元素,这些合并记录了共享元素的AB中的位置:

i = 1
j = 1
shared = []
while i <= length(A) && j <= length(B)
    if sortedApos[i][1] < sortedBpos[j][1]
        ++i
    else if sortedApos[i][1] > sortedBpos[j][1]
        ++j
    else    // They're equal
        append(shared, (sortedApos[i][2], sortedBpos[j][2]))
        ++i
        ++j

最后,按其第一个元素(shared中的位置)对A进行排序,并检查其所有第二个元素(B中的位置)是否正在增加。如果AB共有的元素以相同的顺序出现,则会出现这种情况:

sortedShared = sort(shared[] by first element of each pair)
for i = 2 .. length(sortedShared)
    if sortedShared[i][2] < sortedShared[i-1][2]
        return DIFFERENT

return SAME

时间复杂度:2 *(O(n)+ O(nlog n))+ O(n)+ O(nlog n)+ O(n)= O(nlog n)

答案 2 :(得分:0)

一般方法:将所有值及其在B中的位置存储为HashMap中的键和值。迭代A中的值并在B的HashMap中查找它们以获得它们在B中的位置(或null)。如果此位置之前您之前看到的最大位置值,则您知道B中的某些内容与A的顺序不同。在O(n)时间运行。

粗糙,完全未经测试的代码:

boolean valuesInSameOrder(int[] A, int[] B)
{
  Map<Integer, Integer> bMap = new HashMap<Integer, Integer>();
  for (int i = 0; i < B.length; i++)
  {
    bMap.put(B[i], i);
  }

  int maxPosInB = 0;
  for (int i = 0; i < A.length; i++)
  {
    if(bMap.containsKey(A[i]))
    {
      int currPosInB = bMap.get(A[i]);
      if (currPosInB < maxPosInB)
      {
        // B has something in a different order than A
        return false;
      }
      else
      {
        maxPosInB = currPosInB;
      }
    }
  }

  // All of B's values are in the same order as A
  return true;
}