[链表]5.合并有序链表[快手,京东考过]

题目:将两个有序的链表合并为一个新链表,要求新的链表是通过拼接两个链表的节点来生成的。

例如:0->2->3->7->null,1-->3->5->7->9->null;合并后的链表:0->1->2->3->5->7->7->9->null

解答:本题比较简单:假设两个链表的长度为M和N,直接给出时间复杂度为O(M+N),空间复杂度为O(1)的方法。具体过程如下:

1.如果两个链表一个为空,则无须合并的过程,返回另一个链表的头节点即可。

2.比较head1和head2的值,小的节点也是合并后最小的节点,这个节点无疑是合并节点的头节点,记为head;在之后的步骤中,那个节点的头节点值更小,另一个链表的所有节点都会依次的插入这个链表中

3.不妨设head节点所在的链表为链表1,另一个链表为链表2,链表1和链表2都从头节点开始遍历,比较每次遍历到的两个节点的值,记为cur1和cur2,然后根据大小关系做出不同的调整,同时用一个变量pre表示上次比较时值较小的节点

例如:链表1:1->5->6->null,链表2为:2->3->7->null.

cur1 = 1,cur2 = 2,pre = null.cur1<cur2,不做调整,因为此时cur1较小,所以令pre = cur1=1,然后继续遍历链表1的下一个节点,也就是5.

cur1=5,cur2=2,pre=1.cur2小于cur1,让pre的next指针指向cur2,cur2的next指向cur1,这样cur2便插入到了cur1中。因为此时cur2较小,所以令pre=cur2=2,然后继续遍历cur2的下一个节点,也就是节点3.这样完成后,链表1变成了1->2->5->6->null,链表2变成3->7->null,cur1=5,cur2=2,pre=2.

cur1=5,cur2=3,pre = 3.此时cur2小于cur1,与上一步的调整类似,这一步完成之后,链表1变成了1->2->3->5->6->7->null,链表2变成为7->null,cur1 = 5,cur2 =7,pre=3.

cur1=5,cur2=7,pre =3.此时cur1小于cur2,不做调整,因为此时cur1较小,所以此时pre = cur1 = 5,然后继续遍历cur1的下一个节点,也就是节点6

cur1=6,cur2=7.pre=5.cur1小于cur2,不做调整,因为此时cur1比较小,所以令pre = cur1 = 6;此时链表1已经走到了最后一个节点,再往下就结束,如果链表1或者链表2有任何一个走到了结束,就执行步骤4

4.如果链表1走完,此时cur = null,pre为链表1的最后一个节点,那么就把pre的next指针指向链表2的当前节点(即cur2),表示把链表2没有遍历的部分直接拼接到最后,如果链表2走完,直接把链表1拼接到链表2最后。

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 * }
 */
 public ListNode mergeTwoLists (ListNode l1, ListNode l2) {
        // write code here
        if(l1 == null || l2 == null) return l1 == null ? l2:l1;
        ListNode head = l1.val <= l2.val ? l1:l2; //确定头节点的值
        ListNode cur1 = head == l1 ? l1 : l2;
        ListNode cur2 = head == l1 ? l2 : l1;
        ListNode pre = null; //记录上次比较中较小的节点
        ListNode next = null;
        while( cur1 != null && cur2 != null){
            if(cur1.val <= cur2.val){ //cur1 < cur2,直接赋值 pre = cur1,并且 cur1 = cur1.next;
                pre = cur1;
                cur1 = cur1.next;
            }else{
                next = cur2;//next 节点存储当前cur2节点
                pre.next = cur2;
                cur2.next = cur1; //cur2的下一个节点指向cur1,这样就连接起来了
                pre = cur2;
                cur2 = cur2.next;
            }
        }
        pre.next = cur1 == null ? cur2 : cur1; //链表1或者链表2先遍历完,直接把对方拼接在其后
            
        return head;
    }

解法2:

时间复杂度:O(M+N);

空间复杂度O(M+N);

public class Solution {
    /**
     * 
     * @param l1 ListNode类 
     * @param l2 ListNode类 
     * @return ListNode类
     */
    public ListNode mergeTwoLists (ListNode l1, ListNode l2) {
        // write code here
        ListNode headNode = new ListNode(0);
        ListNode newList = headNode;
        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                newList.next = l1;
                l1 = l1.next;
            }else{
                newList.next = l2;
                l2 = l2.next;
            }
            newList = newList.next;
        }
        newList.next = l1 == null ? l2:l1;
        return headNode.next;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值