📌  相关文章
📜  国际空间研究组织 | ISRO CS 2016 |问题 43(1)

📅  最后修改于: 2023-12-03 15:07:34.556000             🧑  作者: Mango

国际空间研究组织 | ISRO CS 2016 |问题 43

这是一道关于数据结构的经典问题,主要考察了链表的基本操作。该问题涉及两个链表,给定它们的头结点,请将它们合并成一个新的有序链表。

问题描述

给定两个升序排列的链表 L1L2,请把它们合并为一个有序的链表 L3。例如:

L1: 1 -> 3 -> 5 -> 7
L2: 2 -> 4 -> 6 -> 8 -> 10
L3: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 10
解题思路

这道题是一道比较经典的链表合并问题,可以按照以下步骤解决:

  1. 定义一个新的链表 L3,并用一个指针 p 指向它的头结点。

  2. 分别用两个指针 p1p2 分别指向链表 L1L2 的头结点。

  3. 每次比较 p1p2 指向的数据元素,将较小的那个放入 L3 中,并将相应的指针后移一位。

  4. 当其中一个链表被遍历完后,将另一个链表中剩余的元素直接加入 L3 中。

  5. 最后返回 L3 的头结点即可。

下面是该算法的示意图:

  L1: 1 -> 3 -> 5 -> 7
  L2: 2 -> 4 -> 6 -> 8 -> 10
  
   | 
   ↓
  L3:
   p
  L1: 1 -> 3 -> 5 -> 7
  L2: 2 -> 4 -> 6 -> 8 -> 10
  
      | 
      ↓
  L3: 1
   p
  L1: 1 -> 3 -> 5 -> 7
  L2: 2 -> 4 -> 6 -> 8 -> 10
  
         | 
         ↓
  L3: 1 -> 2
      p
  L1: 3 -> 5 -> 7
  L2: 2 -> 4 -> 6 -> 8 -> 10
  
         | 
         ↓
  L3: 1 -> 2 -> 3
           p
  L1: 3 -> 5 -> 7
  L2: 2 -> 4 -> 6 -> 8 -> 10
  
              | 
              ↓
  L3: 1 -> 2 -> 3 -> 4 
                 p
  L1: 5 -> 7
  L2: 2 -> 4 -> 6 -> 8 -> 10
  
              | 
              ↓
  L3: 1 -> 2 -> 3 -> 4 -> 5
                      p
  L1: 5 -> 7
  L2: 2 -> 4 -> 6 -> 8 -> 10
  
                         | 
                         ↓
  L3: 1 -> 2 -> 3 -> 4 -> 5 -> 6
                              p
  L1: 5 -> 7
  L2: 4 -> 6 -> 8 -> 10
  
                         | 
                         ↓
  L3: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7
                                   p
  L1: 7
  L2: 4 -> 6 -> 8 -> 10
  
                         | 
                         ↓
  L3: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
                                        p
  L1: 7
  L2: 6 -> 8 -> 10
  
                         | 
                         ↓
  L3: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 10
                                             p
  L1: 
  L2: 6 -> 8 -> 10
  
                         | 
                         ↓
  L3: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 10
                                                  p
代码实现

下面是该算法的 Python 实现:

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

def merge_two_lists(l1: ListNode, l2: ListNode) -> ListNode:
    dummy = ListNode(-1)
    p = dummy
    
    while l1 and l2:
        if l1.val <= l2.val:
            p.next = l1
            l1 = l1.next
        else:
            p.next = l2
            l2 = l2.next
        p = p.next
    
    if l1:
        p.next = l1
    if l2:
        p.next = l2
    
    return dummy.next

其中 ListNode 是定义链表节点的类,merge_two_lists 是实现链表合并的函数,它接收两个链表的头结点 l1l2,返回合并后的链表的头结点。

在函数中,我们先定义了一个虚拟头结点 dummy,并将指针 p 指向它。这里使用虚拟头结点的意义在于,最终返回的是真正链表的头结点的 next

接下来我们使用 while 循环遍历两个链表,每次将较小的节点加入到新的链表中,并将相应节点的指针向后移动一位。当其中一个链表被遍历完后,我们将另一个链表中剩余的节点都挂载到新链表的尾部。

最后,返回新链表的头结点即可。

总结

链表结构虽然相对于数组来说更为灵活,但是其本身的特点也决定了其在使用时需要更为注意指针的操作,否则容易出现一些错误。这里再次强调算法步骤中需要注意指针的后移操作,避免出现指针漏移等错误。