(中等)LeetCode 328. 奇偶链表 Java

(中等)LeetCode 328. 奇偶链表 Java_第1张图片
对于链表中有零个、一个、两个节点的情况,直接返回即可

对于链表的节点数大于两个的情况,需要讨论,看当前节点是第奇数个节点还是第偶数个节点

class Solution {
    public ListNode oddEvenList(ListNode head) {
        if (head == null || head.next == null || head.next.next == null) {
            return head;
        }

        int cnt = 1;
        ListNode lastNode = head;
        while (lastNode.next != null) {
            cnt++;
            lastNode = lastNode.next;
        }

        int i = 1;
        ListNode p = head;
        ListNode pre = head;
        while (i <= cnt) {
            //第奇数个节点
            if ((i & 1) == 1) {
                pre = p;
                p = p.next;
            } else {
                //第偶数个节点
                pre.next = p.next;
                lastNode.next = p;
                lastNode = lastNode.next;
                lastNode.next = null;
                p = pre.next;
            }
            i++;
        }
        return head;
    }
}

这种方法是一边遍历一边处理

另一种方法,分离节点后合并

如果链表为空,则直接返回链表。

对于每个链表,每个节点是奇数节点或者偶数节点。头节点是奇数节点,头节点的后一个节点是偶数节点,相邻节点的奇偶性不同。因此可以将奇数节点和偶数节点分离成奇数链表和偶数链表,然后将偶数链表连接在奇数链表之后,合并后的链表即为结果链表。

原始链表的头节点head也是奇数链表的头节点以及结果链表的头节点,head的后一个节点是偶数链表的头节点。令evenHead=head.next,则evenHead是偶数链表的头节点。

维护两个指针odd和even分别指向奇数节点和偶数节点,初始时odd=head,even=evenHead。通过迭代的方式将奇数节点和偶数节点分离成两个链表,每一步首先更新奇数节点,然后更新偶数节点。

  • 更新奇数节点时,奇数节点的后一个节点需要指向偶数节点的后一个节点,因此odd.next=even.next,然后令odd=odd.next,此时odd变成even的后一个节点
  • 更新偶数节点时,偶数节点的后一个节点需要指向奇数节点的后一个节点,因此,令even.next = odd.next,然后令even=even.next,此时,even变成odd的后一个节点

在上述操作完成以后,就完成了对一个奇数节点和一个偶数节点的分离。重复上述操作,直到全部节点分离完毕。全部节点分离完毕的条件是even为空节点或者even.next为空节点,此时odd指向最后一个奇数节点(即奇数链表的最后一个节点)

最后令odd.next=evenHead,将偶数链表连接在奇数链表之后,即完成了奇数链表和偶数链表的合并,结果链表的头节点仍然是head

class Solution {
    public ListNode oddEvenList(ListNode head) {
        if (head == null || head.next == null || head.next.next == null) {
            return head;
        }
        ListNode evenHead = head.next;
        ListNode odd = head;
        ListNode even = evenHead;
        //也就是当even或者even.next=null时,退出循环
        //因为even=null退出循环,应该是链表有奇数个节点
        //因为even.next=null退出循环,应该是链表有偶数个节点
        while (even != null && even.next != null) {
            odd.next = even.next;
            odd = odd.next;
            even.next = odd.next;
            even = even.next;
        }
        odd.next = evenHead;
        return head;
    }
}

复杂度分析:

  • 时间复杂度:O(n),其中n是链表的节点数,需要遍历链表中的每个节点,并更新指针
  • 空间复杂度:O(1),只需要维护有限的指针
    (中等)LeetCode 328. 奇偶链表 Java_第2张图片

你可能感兴趣的:(LeetCode,leetcode,链表,java)