NC2 重排链表

将给定的单链表\ L L: L_0→L_1→…→L_{n-1}→L_ nL
0

→L
1

→…→L
n−1

→L
n

重新排序为:L_0→L_n →L_1→L_{n-1}→L_2→L_{n-2}→…L
0

→L
n

→L
1

→L
n−1

→L
2

→L
n−2

→…
要求使用原地算法,不能只改变节点内部的值,需要对实际的节点进行交换。

数据范围:链表长度 0 \le n \le 200000≤n≤20000 ,链表中每个节点的值满足 0 \le val \le 10000≤val≤1000

要求:空间复杂度 O(n)O(n) 并在链表上进行操作而不新建链表,时间复杂度 O(n)O(n)
进阶:空间复杂度 O(1)O(1) , 时间复杂度 O(n)O(n)
示例1
输入:
{1,2,3,4}
复制
返回值:
{1,4,2,3}
复制
说明:
给定head链表1->2->3->4, 重新排列为 1->4->2->3,会取head链表里面的值打印输出 1
示例2
输入:
{1,2,3,4,5}
复制
返回值:
{1,5,2,4,3}
复制
说明:
给定head链表1->2->3->4->5, 重新排列为 1->5>2->4->3,会取head链表里面的值打印输出
示例3
输入:
{}
复制
返回值:
{}

本题,依旧是双指针(链表题目双指针 yyds)首先定义快慢指针,目的是慢指针找到链表的中心节点,找到中心节点以后,反转链表后半部分,此时就相当于链表被分为了两部分,然后再直接拼接就好了

定义 hair 节点,为 head 节点的前一个节点,定义 指针记录 slow 的下一个节点,为后半部分的第一个节点,然后翻转

最后一步拼接链表,nextPre 和 nextRev

NC2 重排链表_第1张图片
记录位置,以及节点的下一个位置

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public void reorderList(ListNode head) {
        ListNode hair = new ListNode(-1);
        hair.next = head;
        ListNode fast = hair, slow = hair;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode nex = slow.next;
        slow.next = null;
        ListNode rev = reverse(nex);
        ListNode pre = head;
        
        while (pre != null && rev != null) {
            ListNode nextPre = pre.next;
            pre.next = rev;
            ListNode nextRev = rev.next;
            rev.next = nextPre;
            pre = nextPre;
            rev = nextRev;
        }
        
    }
    public ListNode reverse(ListNode node) {
        ListNode pre = null;
        while (node != null) {
            ListNode next = node.next;
            node.next = pre;
            pre = node;
            node = next;
        }
        return pre;
    }
}

你可能感兴趣的:(java,LeetCode,算法,链表,数据结构,leetcode)