题目


输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。
数据范围:0≤n≤1000,−1000≤节点值≤1000
要求:空间复杂度 O(1),时间复杂度 O(n)

如输入{1,3,5},{2,4,6}时,合并后的链表为{1,2,3,4,5,6},所以对应的输出为{1,2,3,4,5,6},转换过程如下图所示:

或输入{-1,2,4},{1,3,4}时,合并后的链表为{-1,1,2,3,4,4},所以对应的输出为{-1,1,2,3,4,4},转换过程如下图所示:

示例1

输入:
{1,3,5},{2,4,6}
返回值:
{1,2,3,4,5,6}

示例2

输入:
{},{}
返回值:
{}

示例

输入:
{-1,2,4},{1,3,4}
返回值:
{-1,1,2,3,4,4}

思路1


将链表头小的作为主链表,将另一个链表插入其中。

解答代码1


/**
 * struct ListNode {
 *  int val;
 *  struct ListNode *next;
 *  ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
  public:
    /**
     * @param pHead1 ListNode类
     * @param pHead2 ListNode类
     * @return ListNode类
     */
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        // write code here
        if (pHead1 == nullptr && pHead2 == nullptr) {
            return nullptr;
        } else if (pHead1 != nullptr && pHead2 == nullptr) {
            return pHead1;
        } else if (pHead1 == nullptr && pHead2 != nullptr) {
            return pHead2;
        }
        ListNode* low = nullptr;// 头结点小的链表
        ListNode* top = nullptr;// 头结点大的链表
        if (pHead1->val <= pHead2->val) {
            low = pHead1;
            top = pHead2;
        } else {
            low = pHead2;
            top = pHead1;
        }
        ListNode* ret = low;// 结果指向头结点小的链表,将头结点大的链表数据往里面插入
        ListNode* tmp = nullptr;// 临时节点做缓存
        while (low->next != nullptr && top != nullptr) {// 循环到某个链表为空
            // 结果链表中当前值为最小值,比较low的next的值和top的当前值
            // 如果大于等于,则将top的当前值插入到low当前值的后面
            if (low->next->val >= top->val) {
                tmp = low->next;// 讲tmp指向low的next,临时缓存low的next
                low->next = top;// 将low的next指向top的当前值
                top = top->next;// 让top指针后移
                low->next->next =
                    tmp;// 新插入top(新的low的next)的next指向tmp,也就是缓冲的之前的low的next
            }
            low = low->next; // 让low指针后移
        }
        // 如果头结点小的链表先循环完,则将top剩余的插入到结果后面
        if (low->next == nullptr) {
            low->next = top;
        }

        return ret;
    }
};

思路2


创建一个新链表,将两个旧链表按顺序合入,至一个链表为空,将另一个链表接在后面。

解答代码2


/**
 * struct ListNode {
 *  int val;
 *  struct ListNode *next;
 *  ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
  public:
    /**
     * @param pHead1 ListNode类
     * @param pHead2 ListNode类
     * @return ListNode类
     */
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        // write code here
        if (pHead1 == nullptr && pHead2 == nullptr) {
            return nullptr;
        } else if (pHead1 != nullptr && pHead2 == nullptr) {
            return pHead1;
        } else if (pHead1 == nullptr && pHead2 != nullptr) {
            return pHead2;
        }
        auto new_head = new ListNode(0);// 定义一个头结点
        auto cur = new_head;// 让当前节点指向头结点
        while (pHead1 != nullptr && pHead2 != nullptr) {
            // 取较小的节点加入新表
            if (pHead1->val <= pHead2->val) {
                cur->next = pHead1;
                pHead1 = pHead1->next;
            } else {
                cur->next = pHead2;
                pHead2 = pHead2->next;
            }
            cur = cur->next;
        }
        // 将没有空的链表加到新表后
        if (pHead1 != nullptr) {
            cur->next = pHead1;
        }
        if (pHead2 != nullptr) {
            cur->next = pHead2;
        }
        return new_head->next;// 返回结果不要最开始的头结点
    }
};

ps:一般创建单链表,都会设一个虚拟头结点,也叫哨兵,因为这样每一个结点都有一个前驱结点。


吴尼玛
32 声望11 粉丝

记问之学