143. 重排链表 + 链表翻转 + 快慢指针 + 链表合并

143. 重排链表

LeetCode_143

题目描述

题解分析

  1. 本题的解题核心是需要找到原链表的中间节点,然后将中间节点之后的链表进行反转。
  2. 如何找到中间节点呢?这里可以使用快慢指针的思想,通过设置slow和fast指针,当fast走到尾结点时,slow指针敲好指向中间节点。
  3. 这里的反转链表操作比较简单,也经常考察,我们这里不讲如何反转,而是详细讲一下如何将两个链表进行合并。
  4. 本题有一个坑就是,题目并不要求返回一个新的链表,而是在原有链表中修改next指针来达到合并的目的,这种是交叉合并,其实仔细想还是比较容易实现的。我们每次在迭代时报错list1和list2的next节点,然后修改list1和list2的next指针指向。

代码实现

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public void reorderList(ListNode head) {
        //首先使用快慢指针找到中间结点
        ListNode slow = head, fast = head, pre = null;
        while(fast != null){
            if(fast.next != null)
                fast = fast.next;
            pre = slow;
            slow = slow.next;
            fast = fast.next;
        }
        //接着翻转后半部分链表
        ListNode list2 = reverseLink(slow);//第二个链表是原来链表的后半部分翻转后的结果
        ListNode list1 = head;
        if(pre != null)
            pre.next = null;//第一个链表的尾结点需要为null
        //最后合并两个链表
        merge(list1, list2);
    }
    public ListNode reverseLink(ListNode head){//翻转指定结点的链表部分
        ListNode pre = null;
        while(head != null){
            ListNode temp = head.next;
            head.next = pre;
            pre = head;
            head = temp;
        }
        return pre;
    }
    public void merge(ListNode list1, ListNode list2){//合并两个链表
        while(list1 != null && list2 != null){
            ListNode temp1 = list1.next;
            ListNode temp2 = list2.next;
            list1.next = list2;
            list2.next = temp1;
            list1 = temp1;
            list2 = temp2;
        }
    }
}
posted @ 2021-03-27 21:22  Garrett_Wale  阅读(48)  评论(0编辑  收藏  举报