算法小知识-----8.23-----重排链表

181 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第25天,点击查看活动详情

痛苦周二,截止至今依旧没有拿到画的大饼任务

重排链表

该题出自力扣的143题 —— 重排链表【中等题】,确实是很经典的链表题型

审题

image.png

  • 该题的题意并不复杂,但是相当经典,因为可以一题3用,一道题复习了链表的3个基础
  • 其实就是给出一个链表的头结点,然后返回重新排序后的链表,并且需要按照特定的顺序,1, n , 2, n-1......的顺序
  • 那么这道题有几个解题点
    • 拆分:首先交错的排序,就需要把链表分成两组,正序一组,倒序一组
    • 倒序:正序的分为一组,另一组就需要进行倒序
    • 合并:对两个链表进行合并成一个链表
  • 那么根据这几个解题点就可以分成对应的函数方法
    • 首先找到链表的中点
      • 利用快慢指针,快指针比慢指针快一倍,最终快指针走到结尾null的时候,慢指针也就到达中点
    • 反转链表
      • 利用一个链表空值,作为链表的反转,依次取到链表的下一个,并且反转
      • 从中点的下一个节点开始反转
    • 合并
      • 首先对链表的进行遍历,合并也就是交叉合并,因为题意所提及的是交叉编排

编码

class Solution {
    public void reorderList(ListNode head) {

        // 寻找链表中点
        ListNode mid = findMid(head);
        // 反转链表
        ListNode first = head;
        ListNode second = mid.next;
        mid.next = null;
        second = reverse(second);
        // 合并链表
        mergeNode(first,second);
    }

    private void mergeNode(ListNode l1, ListNode l2) {
        ListNode l1_tmp, l2_tmp;
        while (l1 != null && l2 != null) {
            l1_tmp = l1.next;
            l2_tmp = l2.next;

            l1.next = l2;
            l1 = l1_tmp;

            l2.next = l1;
            l2 = l2_tmp;
        }
    }

    private ListNode reverse(ListNode mid) {
        ListNode result = null;
        ListNode p = mid;
        while (p != null){
            ListNode a = p.next;
            p.next = result;
            result = p;
            p = a;
        }
        return result;
    }

    private ListNode findMid(ListNode head) {
        ListNode first = head,second = head;
        while (second.next != null && second.next.next != null){
            first = first.next;
            second = second.next.next;
        }
        return first;
    }
}

image.png