《剑指offer》面试题25:合并两个排序的链表

题目:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。


链表的节点定义如下:

struct ListNode
{
	int val;
	ListNode* next;
}
思路:

1.当我们得到两个链表中值较小的节点并把它链接到已经合并的链表之后,两个链表剩余的节点依然是排序的,因此合并的步骤和之前的步骤是一样的。这就是典型的递归过程,我们可以定义递归函数完成这一合并过程。
2.一旦输入空的链表就会引入空的指针,因此我们要对空链表单独处理。当第一个链表是空链表,也就是它的头节点是一个空指针时,那么把它和第二个链表合并,显然合并的结果就是第二个链表。同样,当输入的第二个链表的头节点是空指针的时候,我们把它和第一个链表合并得到的结果就是第一个链表。如果两个链表都是空链表,则合并的结果是得到一个空链表。

基于以上思路,java参考代码如下:

package chapter3;


public class P145_MergeSortedLists {
    public static class ListNode{
        int val;
        ListNode next;
        public ListNode(int val){
            this.val=val;
            this.next=null;
        }
    }
    public static void printListNode(ListNode l){
        if(l==null) return;
        while (l!=null){
            System.out.print(l.val);
            System.out.print(" ");
            l=l.next;
        }
        System.out.println();
        return;
    }
    //递归实现:
    public static ListNode mergeSortedList(ListNode head1,ListNode head2){
        if(head1==null) return head2;
        if(head2==null) return head1;
        ListNode cur=null;
        if(head1.val<head2.val){
            cur=head1;
            cur.next=mergeSortedList(head1.next,head2);
        }else {//大于等于的情况都含有
            cur=head2;
            cur.next=mergeSortedList(head1,head2.next);
        }
        return cur;
    }

    //非递归实现:
    public static ListNode mergeSortedList2(ListNode head1,ListNode head2){
        if(head1==null) return head2;
        if(head2==null) return head1;
        ListNode cur1=head1;
        ListNode cur2=head2;
        ListNode cur=null;
        if(cur1.val<cur2.val){//首先将temp指向一个头
            cur=cur1;
            cur1=cur1.next;
        }else{
            cur=cur2;
            cur2=cur2.next;
        }
        while(cur1!=null&&cur2!=null){
            if(cur1.val<cur2.val){
                cur.next=cur1;
                cur1=cur1.next;
            }else {
                cur.next=cur2;
                cur2=cur2.next;
            }
            cur=cur.next;//注意点1:必须每次将temp指针向后移动,才能延长链表
        }
        if(cur1!=null){
            cur.next=cur1;
            //cur1=cur1.next;//注意点2:不必一个一个移动,temp1本身是连接好的
        }else{
            cur.next=cur2;
            //cur2=cur2.next;
        }
        return head1.val<head2.val?head1:head2;
    }

    public static void main(String[] args){
        ListNode head1 = new ListNode(1);
        head1.next= new ListNode(3);
        head1.next.next = new ListNode(5);
        head1.next.next.next = new ListNode(7);
        ListNode head2 = new ListNode(2);
        head2.next= new ListNode(4);
        head2.next.next = new ListNode(6);
        head2.next.next.next = new ListNode(8);
        printListNode(head1);
        printListNode(head2);
        ListNode head =mergeSortedList2(head1,head2);
        printListNode(head);
    }
}


补充:链表排序

java参考代码如下:

public class Solution {
    public ListNode sortList(ListNode head) {//归并排序思想
        if (head == null || head.next == null) return head;
        ListNode slow = head, fast = head, pre = head;
        while (fast != null && fast.next != null) {
            pre = slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        pre.next = null;
        return merge(sortList(head), sortList(slow));
    }
    public ListNode merge(ListNode l1, ListNode l2) {//非递归版
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            } else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        if (l1 != null) cur.next = l1;
        if (l2 != null) cur.next = l2;
        return dummy.next;
    }
}
public class Solution {
    public ListNode sortList(ListNode head) {//归并排序
        if (head == null || head.next == null) return head;
        ListNode slow = head, fast = head, pre = head;
        while (fast != null && fast.next != null) {
            pre = slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        pre.next = null;
        return merge(sortList(head), sortList(slow));
    }
    public ListNode merge(ListNode l1, ListNode l2) {//递归版
        if (l1 == null) return l2;
        if (l2 == null) return l1;
        if (l1.val < l2.val) {
            l1.next = merge(l1.next, l2);
            return l1;
        } else {
            l2.next = merge(l1, l2.next);
            return l2;
        }
    }
}

参考Sort List 链表排序

基于上述思路,C++参考代码如下:

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1==nullptr)     //若指向空,则返回另一个链表的节点
            return pHead2;
        else if(pHead2==nullptr)
            return pHead1;
        ListNode *pnewNode=nullptr;    //定义一个新的链表
        if(pHead1->val < pHead2->val)
        {
            pnewNode=pHead1;
            pnewNode->next=Merge(pHead1->next,pHead2);   //递归
        }
        else
        {
            pnewNode=pHead2;
            pnewNode->next=Merge(pHead1,pHead2->next);   //递归
        }
        return pnewNode;      //返回新链表
    }
};
测试用例:

a.功能测试(输入的两个链表有多个节点;节点的值互不相同或者存在值相等的多个节点)。
b.特殊输入测试(两个链表的一个或者两个头节点为nullptr指针;两个链表中只有一个节点)。

参考:

https://blog.csdn.net/qq_42209189/article/details/80347259

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值