编程题——链表

题目:

  1. 从尾到头打印链表
    输入一个链表,从尾到头打印链表每个节点的值。
  2. 链表中倒数第k个结点
    输入一个链表,输出该链表中倒数第k个结点。
  3. 反转链表
    输入一个链表,反转链表后,输出新链表的表头。
  4. 合并两个排序的链表
    输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
  5. 复杂链表的复制(复制带随机指针的链表)
    输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
  6. 两个链表的第一个公共结点(相交链表)
    输入两个链表,找出它们的第一个公共结点。
  7. 链表中环的入口结点
    一个链表中包含环,请找出该链表的环的入口结点。
  8. 删除链表中重复的结点
    在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
  9. 删除链表中的节点
    请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。(只给定被删除的节点)
    输入: head = [4,5,1,9], node = 5
    输出: [4,1,9]
    解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
  10. 回文链表
    请判断一个链表是否为回文链表。
    示例 1:
    输入: 1->2
    输出: false
    示例 2:
    输入: 1->2->2->1
    输出: true
  11. 链表A+B求和 (两数相加)
    给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
    你可以假设除了数字 0 之外,这两个数字都不会以零开头。
    示例:
    输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
    输出:7 -> 0 -> 8
    原因:342 + 465 = 807
  12. 奇偶链表
    给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
    请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
    示例 1:
    输入: 1->2->3->4->5->NULL
    输出: 1->3->5->2->4->NULL
    示例 2:
    输入: 2->1->3->5->6->4->7->NULL
    输出: 2->3->6->7->1->5->4->NULL
    说明:
    应当保持奇数节点和偶数节点的相对顺序。
    链表的第一个节点视为奇数节点,第二个节点视为偶数节点,以此类推。
  13. 合并K个元素的有序链表
    合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
    示例:
    输入:
    [
    1->4->5,
    1->3->4,
    2->6
    ]
    输出: 1->1->2->3->4->4->5->6
  14. 链表排序
    在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
    示例 1:
    输入: 4->2->1->3
    输出: 1->2->3->4
    示例 2:
    输入: -1->5->3->4->0
    输出: -1->0->3->4->5

代码如下:


1、从尾到头打印链表

输入一个链表,从尾到头打印链表每个节点的值

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*/
//方法1:栈思想:先进后出
public class Solution {
        public ArrayList<Integer> printListFromTailToHead(ListNode listNode) 
        {
            Stack<Integer>stack=new Stack<Integer>();
            ListNode pNode=listNode;
           //入栈
            while(pNode!=null){
                stack.push(pNode.val);
                pNode=pNode.next;
            }
            //出栈
            ArrayList<Integer> al=new ArrayList<>();
            while(!stack.isEmpty()){
                al.add(stack.pop());
            }
                return al;
    }
}

//方法2:递归思想
public class Solution {
    ArrayList<Integer>al=new ArrayList<>();
     public ArrayList<Integer> printListFromTailToHead(ListNode listNode) 
     {
         if(listNode!=null){
             this.printListFromTailToHead(listNode.next);
             al.add(listNode.val);
         }
         return al;
     }
}

2、链表中倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点。

public class FindKthToTail {
    public ListNode FindKthToTail(ListNode head,int k){
        //定义两个指针,p1,p2,
        //倒数第k个,即正数走n-k,总共n-1步,则p1先走k-1步,
        // 然后p1,p2一起走,p1到结尾,此时p2刚好走n-k,到达倒数第k个节点

        if(head==null||k<=0)
            return null;

        ListNode p1=head;
        ListNode p2=head;
        for (int i = 0; i <k-1 ; i++) {
            if(p1.next!=null)
                p1=p1.next;
            else
                return null;//这句至关重要,判断链表长度是否大于k
        }
        while(p1.next!=null){
            p1=p1.next;
            p2=p2.next;
        }
        return p2;
    }

}

3、反转链表

输入一个链表,反转链表**后,输出新链表的表头

public class Solution {
       public ListNode ReverseList(ListNode head) {
         if(head==null)
             return null;
        //当前节点是head,pre为当前节点的前一节点,next为当前节点的下一节点
        //需要pre和next的目的是让当前节点从pre->head->next1->next2变成pre<-head next1->next2
        //即pre让节点可以反转所指方向,但反转之后如果不用next节点保存next1节点的话,此单链表就此断开了
        //所以需要用到pre和next两个节点
        //1->2->3->4->5
        //1<-2<-3 4->5

         ListNode pre=null;
         ListNode next=null;
         ListNode cur=head;

         //pre, head, next
         while(cur!=null)//不是while(cur.next!=null)
         {
             //先用next保存head的下一个节点的信息,保证单链表不会因为失去head节点的原next节点而就此断裂
            // cur=head;
             next=cur.next;

             //保存完next,就可以让head从指向next变成指向pre了,
             cur.next=pre;

             //head指向pre后,就继续依次反转下一个节点
             //让pre,head,next依次向后移动一个节点,继续下一次的指针反转
             pre=cur;
             cur=next;////不是while(cur.next!=null)
         }
         //如果cur为null的时候,pre就为最后一个节点了,但是链表已经反转完毕,pre就是反转后链表的第一个节点
         //直接输出pre就是我们想要得到的反转后的链表
         return pre;
     }        
}

4、合并两个排序的链表

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

public class Solution {
 //方法1:递归思想:先看头结点,谁的头节点小,谁就作为输出链表
    public ListNode Merge(ListNode list1,ListNode list2)
    {
        if(list1==null)
            return list2;
        if(list2==null)
            return  list1;
        //ListNode pMergedHead=null;

        if(list1.val<=list2.val){
           // pMergedHead=list1;
           // pMergedHead.next=Merge(list1.next,list2);
            list1.next=Merge(list1.next,list2);
            return list1;
        }else if(list2.val<list1.val){
            //pMergedHead=list2;
           // pMergedHead.next=Merge(list2.next,list1);
            list2.next=Merge(list2.next,list1);
            return list2;
        }
        //return pMergedHead;
        return null;
    }   
/********************************************************************************/
//方法2:非递归思想1
    public ListNode Merge2(ListNode list1,ListNode list2)
    {
        if(list1==null)
            return list2;
        if(list2==null)
            return  list1;
        //新建一个头节点,用来存合并的链表。
        ListNode pMergedHead=new ListNode(-1);
        pMergedHead.next=null;
        ListNode root=pMergedHead;//root是不变的,pMergedHead一直在变,故不能返回pMergedHead

        while(list1!=null&&list2!=null){
            if(list1.val<=list2.val){
                pMergedHead.next=list1;
                // pMergedHead= list1;
                pMergedHead= pMergedHead.next;
                list1=list1.next;
            }else{
                pMergedHead.next=list2;
                pMergedHead= pMergedHead.next;
                list2=list2.next;
            }
        }
        //谁先为Null,谁短,//把未结束的链表连接到合并后的链表尾部
        if(list1!=null){
            pMergedHead.next=list1;
        }
        if(list2!=null){
            pMergedHead.next=list2;
        }
        return root.next;
    }
/********************************************************************************/    
//方法3: 非递归思想2(类似方法2)
public ListNode Merge3(ListNode list1,ListNode list2)
    {
        if(list1==null)
            return list2;
        if(list2==null)
            return  list1;
        //新建一个头节点(是不变的,指向合并后的第一个节点)
        // 新建当前节点(一直在连接新节点,在变化,不能返回current),
        ListNode pMergedHead=null;
        ListNode current=null;

        while(list1!=null&&list2!=null){
            if(list1.val<=list2.val){
                if(pMergedHead==null){
                    pMergedHead=current=list1;//将pMergedHead指向较小的list1
                }else{
                    current.next=list1;
                    current=current.next;
                }
                list1=list1.next;
            }else{
                if(pMergedHead==null){
                    pMergedHead=current=list2;
                }else{
                    current.next=list2;
                    current=current.next;
                }
                list2=list2.next;
            }
        }
        //谁先为Null,谁短,//把未结束的链表连接到合并后的链表尾部
        if(list1!=null){
            current.next=list1;
        }
        if(list2!=null){
            current.next=list2;
        }
        return pMergedHead;//pMergedHead是始终指向头结点,current目前已经指向了最后一个节点
    }   
}

5、 复杂链表的复制

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
public class Solution {
    public RandomListNode Clone(RandomListNode pHead)
    {
        if(pHead==null)
            return null;
//1. 复制单链表
        RandomListNode pCur=pHead;//pCur指向头结点
        while(pCur!=null)//p指向头结点,只要p不为空,就一直循环
        {
            RandomListNode node=new RandomListNode(pCur.label);//创建新节点,值和pCur相同
            node.next=pCur.next;//插入新节点
            pCur.next=node;

            pCur=node.next;//pCur指向下一个待复制节点
        }

//2. 复制random域
        pCur=pHead;//pCur指向头结点;
        while(pCur!=null)
        {
            if(pCur.random!=null)//有些节点本身就没有random,再访问random的后继就会出现空指针!
            {
                pCur.next.random=pCur.random.next;//A A1 B B1 ,若A->B,则A1->B1 复制节点的random指向 当前节点的random的后一个节点
            }
            pCur=pCur.next.next;//继续遍历下一个
        }
//3.拆分链表:有难度啊,这个拆分啊

        RandomListNode pCloneHead=pHead.next;//复制链表

        RandomListNode temp=pHead;//过渡链表对象,借助此指针,将原链表拆分出去
        pCur=pHead;

        //将原链表拆分出去
        while(pCur.next!=null)
        {
            temp=pCur.next;//指向当前节点的下一个
            pCur.next=temp.next;
            pCur=temp;
        }
        return pCloneHead;

    }
}

6、 两个链表的第一个公共结点

输入两个链表,找出它们的第一个公共结点。

//方法一:很巧秒的思路,不用遍历长度
public class Solution {
  public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode cur1=pHead1;
        ListNode cur2=pHead2;
        while(cur1!=cur2){////如果没有相交,那么curA==null,curB==null时相等,返回null
            cur1=(cur1==null)?pHead2:cur1 .next;
            cur2=(cur2==null)?pHead1:cur2.next;
        }
        return cur1;
    } 
}
//方法2:先遍历两个链表得到长度,较长链表先走差值步,然后同时出发遍历链表,直到到达公共点,或者为Null,时间复杂度0(M+N)

7、链表中环的入口结点。

一个链表中包含环,请找出该链表的环的入口结点

public class Solution {

//方法1:HashSet集合的无重复性,要寻找环的入口节点,遍历节点的时候,遇到的第一个重复节点肯定是入环口节点,
   //所以定义一个Set(不能添加重复数字),添加失败时  即返回环入口节点
    //ListNode 是个指针,比较的时候是比较是否指向同一个对象,也就是该指针的值(既对象的地址)是否相同,
    //和所指对象无关,因此,即使1->1->2又重复数字的也可以,因为对象不同,环是又指向了同一个对象
    public ListNode EntryNodeOfLoop(ListNode pHead){
        if(pHead==null)
            return null;
        ListNode pNode=pHead;
        HashSet<ListNode>pSet=new HashSet<ListNode>();
        while (pNode!=null){
            if(!pSet.add(pNode))
                return pNode;
            else
                pNode=pNode.next;
        }
        return null;
    } 
/*
//方法2:快慢指针
    public ListNode EntryNodeOfLoop(ListNode pHead){
        if(pHead==null)
            return null;
        ListNode pFast=pHead;
        ListNode pSlow=pHead;
        //先判断是否有环,两个指针一个fast、一个slow同时从一个链表的头部出发
        //fast一次走2步,slow一次走一步,如果该链表有环,两个指针必然在环内相遇
        while(pFast!=null&&pFast.next!=null){
            pFast=pFast.next.next;
            pSlow=pSlow.next; 

            if(pFast==pSlow)
                break;//退出整个while循环
        }

        if(pFast==null||pFast.next==null)
            return null;

        //此时只需要把其中的一个指针重新指向链表头部,另一个不变(还在环内),
        //这次两个指针一次走一步,相遇的地方就是入口节点。
        pFast=pHead;
        while(pFast!=pSlow)
        {
            pFast=pFast.next;
            pSlow=pSlow.next;
        }
        return pFast;//否则再次相遇的节点即环入口,自己画画

    }
*/
}

8、 删除链表中重复的结点

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

public class Solution {
    public ListNode deleteDuplication(ListNode pHead)
    {
        //链表为空,或者只有一个节点
        if(pHead==null||pHead.next==null)
            return pHead;

        //1、如果当前头节点是重复节点
        if(pHead.val==pHead.next.val)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
        {                                                                                                                                                           
            ListNode pNode=pHead.next;

            // 跳过值与当前结点相同的全部结点,找到第一个与当前结点不同的结点
            while (pNode!=null&&pNode.val==pHead.val)
            {
                pNode=pNode.next;
            }

            return deleteDuplication(pNode);

        }
        //2、 当前头结点不是重复结点
        else{
            pHead.next=deleteDuplication(pHead.next);// 保留当前结点,从下一个结点开始递归
            return pHead;
        }

    }
}

9、删除链表中的节点

请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。

class Solution {
   public void deleteNode(ListNode node) {//输入:4-5-1-9,删除5
        node.val=node.next.val;//将带删除节点替换为节点的下一个节点,4-1-1-9
        node.next=node.next.next;//单链表的删除操作,4-1-9
    }
}

10、回文链表

请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true

public class IsPalindrome {

//方法1:用快慢指针找到中间元素位置,同时将前半部分入栈,即前半段节点保存在栈里,利用栈后进先出的特点,即从中间向两侧比较,和链表后半段进行比较
 public boolean isPalindrome(ListNode head) {
        //快慢指针,找出链表中间元素,压入栈
        ListNode slow=head;
        ListNode fast=head;
        Stack<Integer> stack=new Stack<>();

        while (fast!=null&&fast.next!=null){
            //入栈
            stack.push(slow.val);
            //快慢指针移动,慢指针依次走一步,快指针一次走两步,当快指针到达尾部,慢指针到达链表中间位置
            slow=slow.next;
            fast=fast.next.next;
        }
        //当链表长度为奇数时,跳过中间元素;如果是偶数,则不用跳过,直接比较即可
        if(fast!=null){//fast==null时,是偶数
            slow=slow.next;
        }
        //将后面元素和栈顶元素比较
        while(slow!=null){
            if(slow.val!=stack.pop()){
                return false;
            }else{
                slow=slow.next;
            }
        }
        return true;
    }
/********************************************************************/

//方法2:用快慢指针找到链表中间元素,将链表后半段反转,前后段链表比较
    public boolean isPalindrome(ListNode head) {//1-2-2-1   1-2-1

        ListNode fast = head;
        ListNode slow = head;
        //快慢指针,快指针到达链表尾部或者尾部下一个时,慢指针指向链表中间
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        //当链表为奇数时,fast指向链表尾节点(fast!=null),慢指针需要跳过中间元素在反转链表
        //当链表为偶数时,fast指向链表尾结点的下一个(fast==null),慢指针所指之后的链表反转,而无需跳过中间元素
        if (fast != null) { // odd nodes: let right half smaller
            slow = slow.next;
        }
        //将链表分成两段,快指针指向第一段头结点,慢指针将链表反转之后,指向反转后的链表头结点
        slow = reverse(slow);//反转慢指针之后的链表  (fast)1->2  null<-2<-1(slow)
        fast = head;

        //快慢指针同时走,比较值是否相同
        while (slow != null) {
            if (fast.val != slow.val) {
                return false;
            }
            fast = fast.next;
            slow = slow.next;
        }
        return true;
    }

    //反转链表 prev slow next
    public ListNode reverse(ListNode slow) {
        ListNode prev = null;
        while (slow != null) {
            ListNode next = slow.next;//先保存下一个
            slow.next = prev;  //指向前一个

            prev = slow;  //prev和slow向后移动
            slow = next;
        }
        return prev;
    }
}

11、 链表A+B求和(两数相加)

给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

特例:
输入:(5) + (5 )
输出:0->1

class Solution {
/*方法1: 相当于边相加边将每一位上计算出来的数字添加到链表中,
前一位的进位加到下一位数字和上。比如(2 -> 4 -> 3) + (5 -> 6 -> 4)中第二个对应数字相加
4+6=10,进位1加到下一位3+4上,即3+4+1=8
*/
 public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if(l1==null)
            return l2;
        if(l2==null)
            return l1;
        //新建链表,填充节点
        ListNode resHead=new ListNode(-1);
        ListNode cur=resHead;

        int curNum=0;//当前位数字和
        int flag=0;//进位

        while(l1!=null||l2!=null||flag!=0){//flag!=0为了计算特例[5] [5],输出[0,1]而不是[0]

            //判断两个链表长度不一样时候,就补0对齐
            int val1=(l1!=null)?l1.val:0;
            int val2=(l2!=null)?l2.val:0;

            curNum=val1+val2+flag;//当前位数字和
            flag=curNum/10; //进位
            cur.next=new ListNode(curNum%10);//和为12,将1进位,2添加到链表

            cur=cur.next;

            //计算链表上下一位对应数字
            l1=l1!=null?l1.next:null;
            l2=l2!=null?l2.next:null;
        }
        //返回链表
        return resHead.next;
    }
}

12、奇偶链表

给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
示例 1:
输入: 1->2->3->4->5->NULL
输出: 1->3->5->2->4->NULL
示例 2:
输入: 2->1->3->5->6->4->7->NULL
输出: 2->3->6->7->1->5->4->NULL
说明:
应当保持奇数节点和偶数节点的相对顺序。
链表的第一个节点视为奇数节点,第二个节点视为偶数节点,以此类推。

public class OddEvenList {
    public ListNode oddEvenList(ListNode head) {
        if(head==null)
            return null;
        //定义两个指针分别指向奇偶序号头部,遍历,当遍历到链表末尾时,将奇链表直接指向偶链表头部即可
        ListNode odd=head,
                even=head.next,
                evenHead=head.next;//定义这个不随遍历变动的变量是为了一直指向偶数序号头部,便于奇尾部直接连上偶数头部
        //1->null  even==null
        //  1->2->null     even.next==null
        // 1->2->3->null  奇数个链表节点时,even指向null,even==null,就该退循环
        // 1->2->3->4->null 偶数个链表节点时,even指向4,但是even.next==null,就该退循环
        while(even!=null&&even.next!=null){
            odd.next=odd.next.next;
            even.next=even.next.next;
            odd=odd.next;
            even=even.next;
        }
        odd.next=evenHead;
        return head;
    }
}

13、合并K个元素的有序链表

合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6

class Solution {
   public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0)
            return null;
        // PriorityQueue 是堆,默认小顶堆
        /*  PriorityQueue<ListNode> queue = new PriorityQueue<ListNode>(11, new Comparator<ListNode>() {
            @Override
            public int compare(ListNode o1, ListNode o2) {
                return o1.val - o2.val;
            }
        });*/
        PriorityQueue<ListNode> queue = new PriorityQueue<>((a, b) -> (a.val - b.val));
        // 加入所有链表的第一个结点,非空
        for (ListNode firstNode : lists)
            if (firstNode != null)
                queue.offer(firstNode);

        ListNode head = new ListNode(-1);
        ListNode cur = head;

        while (!queue.isEmpty()) {
            ListNode temp = queue.poll();
            cur.next = temp;
            cur = cur.next;
            // 边取边加入
            if (temp.next != null)
                queue.offer(temp.next);
        }
        // 注意断链
        cur.next = null;
        return head.next;
    }
}

14、 链表排序

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    //思想:归并排序:将链表分成两部分,分别排序,在合并
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null)
            return head;
        // step 1. 快慢指针将链表分成两段
        ListNode prevSecond=null,
                fast=head,
                slow=head;
        while(fast!=null&&fast.next!=null){
            prevSecond=slow;//prev是第一段末尾,是第二段头结点slow的前一个
            fast=fast.next.next;
            slow=slow.next;
        }
        prevSecond.next=null;

        // step 2. 两段分别排序
        ListNode l1=sortList(head);
        ListNode l2=sortList(slow);

        // step 3. merge l1 and l2
        return merge(l1,l2);
    }
    //将两个有序链表合成一个有序链表
    ListNode merge(ListNode l1,ListNode l2){
        ListNode head=new ListNode(-1);
        ListNode p=head;
        while(l1!=null&&l2!=null){
            if(l1.val<l2.val){
                p.next=l1;
                l1=l1.next;
            }else{
                p.next=l2;
                l2=l2.next;
            }
            p=p.next;
        }
        //谁先为Null,谁短,//把未结束的链表连接到合并后的链表尾部
        if(l1!=null)p.next=l1;
        if(l2!=null)p.next=l2;

        return head.next;
    }
}

猜你喜欢

转载自blog.csdn.net/hefenglian/article/details/80811353