143. 重排链表

204 阅读1分钟

方法一:反转 + 找中点 + 合并两个链表

  • 找链表中点
  • 翻转后半段(不含中点)
  • 截取前半段
  • 合并

610776B0D5049D6CF0FCED042B1FB78E.png

class Solution {
    public void reorderList(ListNode head) {
        //找链表的中点
        ListNode fast = head, slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        //此时slow为中点,偶数靠后
        ListNode newHead = slow.next;
        slow.next = null; // 截断
        //翻转中点后的那一段链表
        ListNode pre = null;
        ListNode cur = newHead;
        while (cur != null) {
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        //合并后半段和前半段,此时pre为反转后的头
        merge(head, pre);
    }

    // 交替合并两个链表
    public void merge(ListNode node1, ListNode node2) {
        while (node1 != null && node2 != null) {
            ListNode tmp1 = node1.next;
            node1.next = node2;
            node1 = tmp1;

            ListNode tmp2 = node2.next;
            node2.next = node1;
            node2 = tmp2;
        }
    }
}

方法二: 把node存到list中,然后碰撞指针依次添加

class Solution {
    public void reorderList(ListNode head) {
        if (head == null) return;
        List<ListNode> list = new ArrayList<>();
        ListNode cur = head;
        while (cur != null) {
            list.add(cur);
            cur = cur.next;
        }
        int i = 0;
        int j = list.size() - 1;

        while(i != j) {
            list.get(i).next = list.get(j);
            i++;
            if (i == j) break;
            list.get(j).next = list.get(i);
            j--;
        }
        list.get(i).next = null;
    }
}