每日打卡:重排链表

90 阅读2分钟

这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

L0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为:

L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

原题链接

今天的这道题,他看起来好麻烦的样子,但其实,我们不要被他的等级吓到了,做起来还是很好去实现的,我们只要理顺了,我们链表重新排列之后的顺序是什么样子的就十分好做了。

40E1CA1B5C95679A491CA8CA891B5402.jpg 我们把这个过程分为三部分

1.把链表从中间分割成两部分,返回中间节点

    //我们使用快慢指针,慢指针走一步,快指针走两步,当快指针走到终点时,慢指针处于中间位置
    public ListNode mid(ListNode head){
        ListNode slow = head;
        ListNode fast = head;
        while(fast.next!=null && fast.next.next!=null){
            slow=slow.next;
            fast=fast.next.next;
        }
        return slow;
    }

2.反转后半部分链表

    //这个就是我们正常反转链表的操作
    public ListNode reverseList(ListNode head){
        ListNode p = null;
        ListNode n = head;
        while(n!=null){
            ListNode temp = n.next;
            n.next = p;
            p=n;
            n=temp;
        }
        return p;
    }

3.一次合并两部分链表

    public void mergeList(ListNode l1,ListNode l2){
        ListNode a=l1;
        ListNode b=l2;
        while(a!=null && b!=null){
            ListNode atemp = a.next;
            ListNode btemp = b.next;
            
            a.next=b;
            a=atemp;

            b.next=a;
            b=btemp;
        }
    }

当我们有这些方法之后,我们简单的操作一下

 public void reorderList(ListNode head) {
        if(head==null){
            return;
        }
        //获取我们的中间节点
        ListNode mid = mid(head);
        ListNode a=head;
        ListNode b=mid.next;
        //我们的a链表现在表示的是全部的链表,我们要从中间,将链表截断,就需要让它中间的指针指向null就可以了
        mid.next=null;
        b=reverseList(b);  
        mergeList(a,b);
    }

之前就做了很多的链表的题,有过反转链表,有过合并链表,这一道题像把链表很多的知识点都集中起来,一起去运用,如果直接没有看过其他的题有这种办法去解题还是很难的,但是其它类型的题我刚刚做完,就遇上了。