算法题:合并有序链表

60 阅读1分钟

下面是合并两个已排序的链表并返回合并后的排序链表:

// 定义链表节点类(假设这个类已经在其他地方被定义)
class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        // 虚拟头结点
        ListNode dummy = new ListNode(-1), p = dummy;
        ListNode p1 = l1, p2 = l2;
        
        while (p1 != null && p2 != null) {
            // 比较 p1 和 p2 两个指针
            // 将值较小的的节点接到 p 指针
            if (p1.val > p2.val) {
                p.next = p2;
                p2 = p2.next;
            } else {
                p.next = p1;
                p1 = p1.next;
            }
            // p 指针不断前进
            p = p.next;
        }
        
        if (p1 != null) {
            p.next = p1;
        }
        
        if (p2 != null) {
            p.next = p2;
        }
        
        return dummy.next;
    }
}

注意:在上面的代码中,我添加了一些注释来解释每个步骤的目的。 另外,我提到了关于if (l2 != null)这部分代码的冗余性。 由于while循环的条件是l1 != null && l2 != null,所以当while循环结束时,至少有一个链表已经被完全遍历并合并到了结果链表中。 因此,在while循环之后,我们只需要检查并附加剩余的那个链表(如果有的话)到结果链表的末尾。

在这个例子中,由于我们已经在else块中处理了l2的情况(当l1.val >= l2.val时),所以不需要再显式地检查l2是否为null, 因为如果l2不为null,它肯定已经被附加到了结果链表的末尾。 不过,为了保持代码的清晰和对称性,有时保留这个看似多余的检查也是可以的。