奇偶链表
给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
示例1:
输入: 1->2->3->4->5->NULL
输出: 1->3->5->2->4->NULL
示例2
输入: 2->1->3->5->6->4->7->NULL
输出: 2->3->6->7->1->5->4->NULL
说明
应当保持奇数节点和偶数节点的相对顺序。
链表的第一个节点视为奇数节点,第二个节点视为偶数节点,以此类推。
思路分析:
- 暂且不考虑题目要求,笨方法就是分别构造一个奇偶链表,最后将两个链表拼接起来。简单粗暴,空间要求O(n)即可。
- 空间O(1)要求我们对原链表原地操作,如果我们先将奇数下标节点连起来,会发现偶数下标的节点连不起来了,很容易就想到我们需要将奇偶下标的节点在循环遍历时交叉依次连接,这里我们需要两个可动指针。
- 最后处理奇偶链表拼接时,我们会发现,奇链表找不到偶链表,所以我们还需要记录偶链表的头结点。
- 当整个链表的长度为奇数个时,我们只需要将最后一个节点和偶链表头连接,当链表的长度为偶数个时,我们需要将倒数第二个节点和偶链表的头连接,至此,算法生成。
代码:
public ListNode oddEvenList(ListNode head) {
//先判断链表满足的条件
if(head==null||head.next==null||head.next.next==null) {
return head;
}
//首先记录前头节点,再额外提供两个可以动的节点遍历链表
ListNode second = head.next, front = head,rear = head.next;
int count = 0;
//进行遍历
while(true) {
if(rear.next==null) {
//结束循环的条件分为奇数个节点和偶数个节点两种
if(count%2==0) {
//偶数个节点
front.next = second;
}else {
front.next = null;
rear.next = second;
}
break;
}
front.next = rear.next;
front = rear;
rear = rear.next;
++count;
}
return head;
}