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

发布于 2024-09-28 22:12:12 字数 283 浏览 2 评论 0原文

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

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

I have two ordered lists of the same element type, each list having at most one element of each value (say ints and unique numbers), but otherwise with no restrictions (one may be a subset of the other, they may be completely disjunct, or share some elements but not others).

How do I efficiently determine if A is ordering any two items in a different way than B is? For example, if A has the items 1, 2, 10 and B the items 2, 10, 1, the property would not hold as A lists 1 before 10 but B lists it after 10. 1, 2, 10 vs 2, 10, 5 would be perfectly valid however as A never mentions 5 at all, I cannot rely on any given sorting rule shared by both lists.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

爱的那么颓废 2024-10-05 22:12:12

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

You can get O(n) as follows. First, find the intersection of the two sets using hashing. Second, test whether A and B are identical if you only consider elements from the intersection.

挖个坑埋了你 2024-10-05 22:12:12

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

My approach would be to first make sorted copies of A and B which also record the positions of elements in the original lists:

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)

Now find those elements in common using a standard list merge that records the positions in both A and B of the shared elements:

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

Finally, sort shared by its first element (position in A) and check that all its second elements (positions in B) are increasing. This will be the case iff the elements common to A and B appear in the same order:

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

Time complexity: 2*(O(n) + O(nlog n)) + O(n) + O(nlog n) + O(n) = O(nlog n).

多情癖 2024-10-05 22:12:12

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

General approach: store all the values and their positions in B as keys and values in a HashMap. Iterate over the values in A and look them up in B's HashMap to get their position in B (or null). If this position is before the largest position value you've seen previously, then you know that something in B is in a different order than A. Runs in O(n) time.

Rough, totally untested code:

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文