leetcode刷题日记-【328. 奇偶链表】

268 阅读3分钟

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

题目描述

给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。

第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。

请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。

你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题。

 

示例 1:

image.png

输入: head = [1,2,3,4,5] 输出: [1,3,5,2,4] 示例 2:

image.png

输入: head = [2,1,3,5,6,4,7] 输出: [2,3,6,7,1,5,4]  

提示:

  • n ==  链表中的节点数
  • 0 <= n <= 104
  • -106 <= Node.val <= 106

题目元素

给定一个链表,将链表中的节点按照元素所在索引的奇偶性分开,奇数在前,偶数在后,除此之外链表元素

链表元素交换,思路仍旧是三个元素

哑元节点

设置一个值为空的链表,将真实链表放入它的next属性,这样在操作所有链表时不用考虑首节点的特殊性,这里以为是将奇偶数分开,所以可以把这个问题看成将链表中的元素按照奇偶性分成2个链表,所以这里需要2个哑元节点;

虚拟节点

这里需要将奇偶数分开,所以需要2个虚拟节点,它们分别指向奇数链表和偶数链表的当前操作节点,每次移动后该值都会向后移动,结束之后只需要将奇数的虚拟节点所在的next节点设置为偶数的雅苑节点的next,即可得到最终答案。

链表移动

链表的移动其实就是将当前操作节点向后移动,并将节点的next赋值到虚拟节点上,截止条件为当前操作节点为空。

难点在于链表对象的重新指向,可以多总结做题规律,然后会发现它们的套路都是差不多的。

实现步骤

创建一个当前遍历的操作节点tail,即链表移动的当前节点;

为奇偶链表分别设置哑元节点和虚拟节点,虚拟节点分别指向奇数链表和偶数链表的最后一个元素;

设置一个索引下标index,初始值为1,因为根据题意所以是从1开始计算的;

遍历tail,判断索引奇偶性,根据奇偶性将它们放入对应的链表中,此时注意指针后移,即奇偶链表的虚拟节点始终指向它所代表的链表的最后一个元素;

链表移动,将tail赋值为tail.next,且索引自增1;

循环结束后,即链表内所有元素都重新放入了对应的奇偶链表中,此时需要注意,因为偶数链表是放在后面的,所以它的最后一个元素next一定要重新设置为null;

将偶数链表放入奇数最后一个节点的next中,然后再将偶数链表的哑元节点的next(真实链表)放入奇数链表的最后一个节点的next中。

最终的奇数哑元节点的next就是生成的新链表。

代码实现

public static ListNode oddEvenList(ListNode head) {
    // 设置当前操作节点 初始化为一个哑元节点,即将真实需要遍历的节点放入这个节点的next中,每次遍历next即可
    ListNode tail = new ListNode();
    tail.next = head;
    // 设置奇偶链表的哑元节点
    ListNode oddDummyNode = new ListNode();
    ListNode evenDummyNode = new ListNode();
    // 奇数 指向最后一个操作的节点
    ListNode oddTail = oddDummyNode;
    // 偶数 指向最后一个操作的节点
    ListNode evenTail = evenDummyNode;
    int index = 1;
    while (tail.next != null) {
        if (index % 2  == 0) {
            // 偶数
            evenTail.next = tail.next;
            // 始终指向最后一个操作节点
            evenTail = tail.next;
        } else {
            // 奇数
            oddTail.next = tail.next;
            oddTail = tail.next;
        }
        tail = tail.next;
        index ++;
    }
    evenTail.next = null;
    oddTail.next = evenDummyNode.next;
    // 交换位置
    return oddDummyNode.next;
}