【问题标题】:How can I efficiently determine if two lists contain elements ordered in the same way?如何有效地确定两个列表是否包含以相同方式排序的元素?
【发布时间】:2010-10-23 20:03:06
【问题描述】:

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

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

【问题讨论】:

    标签: algorithm sorting set


    【解决方案1】:

    你可以得到 O(n) 如下。首先,使用散列法找到两个集合的交集。其次,如果只考虑交点中的元素,则测试 A 和 B 是否相同。

    【讨论】:

    • 我就是这么想的。将列表相交并进行比较。
    • O(n) 将列表转换为基于哈希的集合,O(n) 将每个列表与其他列表进行比较,以形成仅包含重叠元素的列表,以及 O(n) 比较那些列表。太棒了!
    【解决方案2】:

    我的方法是首先制作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)

    【讨论】:

      【解决方案3】:

      一般做法:将 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;
      }
      

      【讨论】:

        猜你喜欢
        • 2010-12-13
        • 2020-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-11
        • 2022-01-16
        • 2010-11-07
        相关资源
        最近更新 更多