https://leetcode-cn.com/problems/odd-even-linked-list/
难度中等
给定单链表的头节点
head
,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。
请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。
你必须在
O(1)
的额外空间复杂度和O(n)
的时间复杂度下解决这个问题。示例 1:
输入: head = [1,2,3,4,5]
输出: [1,3,5,2,4]
示例 2:
输入: head = [2,1,3,5,6,4,7]
输出: [2,3,6,7,1,5,4]
提示:
n = 链表中的节点数
0 <= n <=
-10<= Node.val <=
方法一:分别构建奇数链表及偶数链表,将二者合并。
public static ListNode oddEvenList (ListNode head) { //节点只有一个或两个,直接返回 if(head == null || head.next == null) { return head; } ListNode oddHead = head; //奇数节点指针 ListNode evenHead = head.next; //偶数节点指针 ListNode evenDummy = new ListNode(0); //偶数节点的哑节点 evenDummy.next = evenHead; while (evenHead != null && evenHead.next != null) { oddHead.next = evenHead.next; //奇数节点指针指向偶数节点指针的后一位 oddHead = oddHead.next; //奇数节点指针后移一位 evenHead.next = oddHead.next; //偶数节点指针指向奇数节点指针的后一位 evenHead = evenHead.next; //偶数节点指针后移一位 } //将偶数节点拼接在奇数节点末尾 oddHead.next = evenDummy.next; return head; }
方法二:不拆分为两个链表,动态地在一条链表上原地修改。
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> NULL 重排前一对
1 -> 3 -> 2 -> 4 -> 5 -> 6 -> 7 -> 8 -> NULL 重排前两对
1 -> 3 -> 5 -> 2 -> 4 -> 6 -> 7 -> 8 -> NULL 重排前三对
1 -> 3 -> 5 -> 7 -> 2 -> 4 -> 6 -> 8 -> NULL 重排前四对
......public static ListNode oddEvenList (ListNode head) { if(head == null || head.next == null) { return head; } ListNode front = head; //排好的奇数序号节点的尾部 ListNode pre = front.next; //待排的奇数节点的前一个结点(排好的偶数节点的尾部) ListNode cur = pre.next; //待排的奇数节点的头部 while(cur != null) { pre.next = cur.next; cur.next = front.next; front.next = cur; pre = pre.next; //后移一位 front = front.next; //后移一位 if(pre == null) break; cur = pre.next; //置为 pre 的下一个节点(pre 可能是 null, pre 跑的最快) } return head; }