【问题标题】:Merge two linked lists without duplicities合并两个没有重复的链表
【发布时间】:2021-12-29 04:38:09
【问题描述】:

给定两个排序的链表,结果应该是无重复的并集。

  • 不允许创建新节点。
  • 结果列表将由原始列表的元素组成。

输入是由空行分隔的两个列表:

L1 -> 2 3 3 4 4 4 5

L2 -> 3 4 5 5 6 7

结果 -> 2 3 4 5 6 7

我在下面有我的解决方案,但在 Union 函数中创建新节点。

有没有什么简单的方法可以改变Union函数的逻辑,不创建任何新节点并删除重复项?

class Node:
    def __init__(self, data, next = None):
        self.data = data
        self.next = next

def PrintLinkedList( p ):
    print( "Result:", end=" " )
    while p!=None:
        print( p.data, end=" " )
        p = p.next
    print(".")

def ReadLinkedList():
    first = None
    last = None
    r = input()
    while r!="":
        row = r.split()
        if len(row)==0:
            break
        for s in row:
            p = Node(int(s),None)
            if first==None:
                first = p
            else:
                last.next = p
            last = p
        r = input()
    return first

def dedup(head):
    current = head
    while current:
        runner = current
        # Check, until runner.next is not None.
        while runner.next:
            if current.data == runner.next.data:
                runner.next = runner.next.next
            else:
                runner = runner.next
        current = current.next

def Union(a, b):

    # A dummy node to store the result
    dummyNode = Node(0)
    headA = a
    headB = b

    # Tail stores the last node
    tail = dummyNode
    while True:

        # If any of the list gets completely empty
        # directly join all the elements of the other list
        if headA is None:
            tail.next = headB
            break
        if headB is None:
            tail.next = headA
            break

        # Compare the x of the lists and whichever is smaller is
        # appended to the last of the merged list and the head is changed
        if headA.data <= headB.data:
            tail.next = headA
            headA = headA.next
        else:
            tail.next = headB
            headB = headB.next

        # Advance the tail
        tail = tail.next

    # Delete dups and returns the head of the merged list
    dedup(dummyNode.next)
    return dummyNode.next

【问题讨论】:

  • 您可以在合并时重用任何列表的节点。而不是创建新节点,只需使用两个列表中的任何一个节点。因为根据任务,您可以修改给定的列表,因此可以将它们的节点用于/修改用于您需要的任何目的。

标签: python python-3.x algorithm linked-list singly-linked-list


【解决方案1】:

第 1 部分

在不修改您的解决方案的情况下,我决定实现自己的解决方案,它不会创建任何新节点。它执行常规的合并排序算法。请参阅我的答案的第 2 部分以获得更短的解决方案。

Try it online!

class Node:
    def __init__(self, data, next = None):
        self.data = data
        self.next = next

def create_list(l):
    n = None
    for e in reversed(l):
        n = Node(e, n)
    return n

def print_list(l):
    if l is None:
        return
    else:
        print(l.data, end = ' ')
        print_list(l.next)

def main():
    l1, l2 = [list(map(int, input().split())) for i in range(2)]
    l1, l2 = create_list(l1), create_list(l2)
    
    r = None
    head = None
    last = None
    
    while True:
        if l1 is None and l2 is None:
            break
        
        if l2 is None or l1 is not None and l1.data <= l2.data:
            if last is None or last < l1.data:
                if r is None:
                    r = l1
                    head = r
                else:
                    r.next = l1
                    r = r.next
            last = l1.data
            l1 = l1.next
        elif l1 is None or l2.data < l1.data:
            if last is None or last < l2.data:
                if r is None:
                    r = l2
                    head = r
                else:
                    r.next = l2
                    r = r.next
            last = l2.data
            l2 = l2.next

    print_list(head)
            
main()

输入:

2 3 3 4 4 4 5
3 4 5 5 6 7

输出:

2 3 4 5 6 7

第 2 部分

可以注意到,在我上面的代码中,l1l2 部分代码是对称的,因此我使用 l[i] 而不是 l1l2 使代码更简单(更短),其中索引i 表示我们是否使用l1 (l[0]) 或l2 (l[1])。这是简化的代码:

Try it online!

class Node:
    def __init__(self, data, next = None):
        self.data = data
        self.next = next

def create_list(l):
    n = None
    for e in reversed(l):
        n = Node(e, n)
    return n

def print_list(l):
    if l is not None:
        print(l.data, end = ' ')
        print_list(l.next)

def main():
    l = [create_list(list(map(int, input().split()))) for i in range(2)]
    r, head, last = [None] * 3
    
    while l[0] is not None or l[1] is not None:
        i = [1, 0][l[1] is None or l[0] is not None and l[0].data <= l[1].data]
        if last is None or last < l[i].data:
            if r is None:
                r = l[i]
                head = r
            else:
                r.next = l[i]
                r = r.next
        last = l[i].data
        l[i] = l[i].next
    
    print_list(head)
            
main()

【讨论】:

  • 非常感谢@Arty,这看起来简单多了。
  • @Marian 刚刚想出了如何缩短两倍的代码,请阅读我更新答案的第 2 部分。这种简化源于l1l2 的代码完全相同,因此我们可以通过l[i] 将其缩短两倍,其中索引i 表示它是列表l1 还是l2
【解决方案2】:

我建议单独处理第一个节点,这样您就知道合并列表的头部是什么。您的其余代码可以保持不变:

def Union(a, b):
    if a is None or b is None:  # Deal with this trivial case
         a = a or b
         dedup(a)
         return a

    headA = a
    headB = b

    # Tail stores the last node: process first node
    if headA.data <= headB.data:
        tail = headA
        headA = headA.next
    else:
        tail = headB
        headB = headB.next
    head = tail  # Remember what the head is of the merged list
    while True:
        if headA is None:
            tail.next = headB
            break
        if headB is None:
            tail.next = headA
            break
        if headA.data <= headB.data:
            tail.next = headA
            headA = headA.next
        else:
            tail.next = headB
            headB = headB.next

        # Advance the tail
        tail = tail.next

    # Delete dups and returns the head of the merged list
    dedup(head)
    return head

【讨论】:

  • 谢谢@trincot!看起来“处理这个琐碎的案例”无法正常工作。如果 L1 为空且 L2 不为空,则应返回 L2。
  • 抱歉,它假设dedup 也会返回结果列表。我现在看到你的函数没有返回任何东西。所以我已经纠正了这种情况。您可能仍然想在dedup 中实际返回。它允许编写更短的代码。
  • 抱歉,我忽略了它。非常感谢您的快速修复!
猜你喜欢
  • 2019-01-28
  • 2012-04-17
  • 2014-01-15
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 2019-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多