21. 合并两个有序链表

332 阅读1分钟

题目介绍

力扣21题:leetcode-cn.com/problems/me…

image.png

分析

给你输入两个有序链表,请你把他俩合并成一个新的有序链表,函数签名如下:

ListNode mergeTwoLists(ListNode l1, ListNode l2);

这题比较简单,我们直接看解法:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        // 虚拟头结点
        ListNode dummy = new ListNode(-1);
        ListNode p = dummy;
        ListNode p1 = l1, p2 = l2;

        while(p1 != null && p2 != null) {
            // 比较 p1 和 p2 两个指针
            // 将值较小的的节点接到 p 指针
            if(p1.val < p2.val) {
                p.next = p1;
                p1 = p1.next;
            }else {
                p.next = p2;
                p2 = p2.next;
            }
            // p 指针不断前进
            p = p.next;
        }
        
        //如果l1还没有遍历完,直接拼接到p指针后面
        if(p1 != null) {
           p.next = p1; 
        }
        
        //如果l2还没有遍历完,直接拼接到p指针后面
        if(p2 != null) {
           p.next = p2; 
        }
        return dummy.next;
    }
}

我们的 while 循环每次比较p1p2的大小,把较小的节点接到结果链表上:

这个算法的逻辑类似于「拉拉链」,l1, l2类似于拉链两侧的锯齿,指针p就好像拉链的拉索,将两个有序链表合并。

代码中还用到一个链表的算法题中是很常见的「虚拟头节点」技巧,也就是dummy节点。你可以试试,如果不使用dummy虚拟节点,代码会复杂很多,而有了dummy节点这个占位符,可以避免处理空指针的情况,降低代码的复杂性。