Java 合并有序列表

Java 合并有序列表,java,Java,请允许我举个例子问这个问题: 假设我们有以下3个列表(为了清楚起见,省略了双引号): 输出列表可以如下所示(还有更多解决方案) 总之,生成的有序集 包含所有列表中元素的并集 保留所有原始列表中元素的顺序 第四个列表L4:(b,c,d)当添加到输入时,应该抛出一个异常(因为在L1中c位于b之前) 我通过检查得出了答案。有人能提出一个算法来做这件事吗? 谢谢,-M.S.这可以使用 首先从列表中构建有向图。列表中的元素将成为节点。边从第一个元素到第二个元素,从第二个元素到第三个元素,依此类推 根据

请允许我举个例子问这个问题: 假设我们有以下3个列表(为了清楚起见,省略了双引号):

输出列表可以如下所示(还有更多解决方案)

总之,生成的有序集

  • 包含所有列表中元素的并集
  • 保留所有原始列表中元素的顺序
第四个列表L4:(b,c,d)当添加到输入时,应该抛出一个异常(因为在L1中c位于b之前)

我通过检查得出了答案。有人能提出一个算法来做这件事吗? 谢谢,-M.S.

这可以使用

首先从列表中构建有向图。列表中的元素将成为节点。边从第一个元素到第二个元素,从第二个元素到第三个元素,依此类推

根据您实现算法的方式,您可以得到所有可能的解决方案,或者只有一个。此外,如果图形包含一个循环,则算法将因错误而停止

以下是列表中的图形的外观:

资料来源:

digraph {
  {
    edge [color = "red"]
    a -> c
    c -> b
    b -> d
    d -> f
    f -> j
  }
  {
    edge [color = "blue"]
    b -> e
    e -> j
    j -> k
  }
  {
    edge [color = "green"]
    a -> d
    d -> e
    e -> g
    g -> h
    h -> j
    j -> i
  }
}

这是一个尝试。通常的免责声明适用

主逻辑

本质上,这是一个两步的过程

1.将3个列表转换为一个双链接列表,每个节点都指向下一个元素,并使用第二个指针指向任何同级(如e/f或i/k)。转换后,它应该看起来像

a->c->b->d->f->g->h->j->k
            |           |
            e           i
2.编写一个函数,该函数包含两个元素和上面的链表,并返回一个标志,指示第一个元素是出现在第二个元素之前、之后还是与第二个元素位于同一位置。该方法的一个可能特征可能是

int getRelativePositionOf(char e1, char e2)
//returns -1 if e1 exists before e2, 0 if e1 and e2 are siblings and 1 if e1 exists after e2.
这将帮助您验证第四个列表,并在任意两个元素的相对位置与原始数据不同时引发异常

创建链接列表

可以想象,第一步,即创建双链接列表是最具挑战性的部分。我还没有想出最优雅的方法来创造它,但这里有一个

  • 将最长的列表L1放入 双链接列表。因此,在您的示例中,这是第三个列表,您现在将 有

  • 现在遍历其余的元素 对于每个元素,检查它是否存在于链接列表中。如果有,忽略它

  • 如果该元素不存在,则需要将其插入到链表中。现在我们需要找出这个元素应该添加到的位置。让我们称这个元素为“X”

  • 遍历链表的长度,对于每个元素,如“Y”,在L2和L3中检查X和Y之间是否存在位置关系。例如,如果我们试图将“c”插入上述链表,我将从链表的第一个元素开始,即“a”,并在列表中查看“a”和“c”之间是否存在关系

  • 如果我们能够确定两个元素在原始列表中的相对位置,那么关系就被定义为存在。从第一个列表中,我知道“c”在“a”之后。所以“c”应该插入“a”之后的某个地方。所以我们在链表中继续前进,现在比较'd'和'c'。同样从第一个原始列表中,我们知道“c”在“d”之前。答对 了在“a”和“d”之间插入“c”。因此,链表现在变为

    a->c->d->->e->g->h->j->i

  • 如果无法确定两个元素之间的关系,则它们是兄弟元素。因此,如果您尝试在上面的列表中插入“f”,您会知道它应该在“d”之后和“g”之前,但没有关于它的相对位置wrt“e”的信息。因此,将“f”存储为“e”的兄弟

  • 执行此操作直到插入所有元素


  • 显然,步骤5是上述算法中最丑陋、最棘手的部分。但我认为可以对其进行优化,使其更简单、更快。例如,您可以从原始列表中创建char->position的hashmaps,以便在确定相对位置时更快地查找。此外,您还可以维护一组已存在于链表中的所有元素,以避免在该元素已存在时遍历链表。我相信有很多方法可以进一步优化它。

    我不是专家,但看起来这可以通过基于图形的数据结构来实现。你说的是合并有序列表-在我看来,它们没有顺序。有什么想法吗,Rahul?我在考虑深度优先树搜索,但这可能不太好。可能是O(n3)Romain,前3个列表都是按字母顺序排列的,不是按字母顺序排列的,而是按其他一些标准排列的。
    a->c->b->d->f->g->h->j->k
                |           |
                e           i
    
    int getRelativePositionOf(char e1, char e2)
    //returns -1 if e1 exists before e2, 0 if e1 and e2 are siblings and 1 if e1 exists after e2.
    
    a->d->e->g->h->j->i