给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 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(nodes),且不能循环定义变量(空间复杂O(1))
1.设置两个指针odd(表示奇数位置节点)和even(表示偶数位置节点)
2.odd从head开始;even从head.next开始,并存储该位置为evenStart
3.试想一个问题,odd和even同时后移两个单位,则even先到链表末尾
4.所以根据3的特性,odd的下一跳为odd的下两跳,even的下一跳为even的下两跳,并更新odd和even的位置为当前的下一跳,直到even先到达末尾为止
5.此时奇数位节点已被odd指针串接,偶数位节点已被even指针串接
6.将在2中记录的evenStart作为odd的下一跳,奇偶链表完成,返回head节点即可
图解
代码实现
class Solution {
public ListNode oddEvenList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode odd = head; //奇数结点
ListNode even = head.next;
ListNode evenStart = even; //定义偶数结点的第一个结点
while (even != null && even.next != null) {
odd.next = even.next;//odd的下一跳为odd的下两跳,将奇数结点串起来
odd = odd.next; //odd角标后移
even.next = odd.next;//even的下一跳为even的下两跳,将偶数结点串起来
even = even.next; //even角标后移
}
odd.next = evenStart; //偶数结点串在奇数结点的后面
return head; //返回排序后链表的第一个结点
}
}
解法2