题目描述
给定一个单链表,将所有奇数节点放在前面,偶数节点放在后面。要求保持原始相对顺序。
例如: 输入: 1->2->3->4->5->NULL 输出: 1->3->5->2->4->NULL
解法
要解决这个问题,可以使用两个指针 odd 和 even 分别指向奇数节点和偶数节点的位置。然后遍历链表,每次将当前节点添加到对应的奇数或偶数链表的末尾,并分别更新 odd 和 even 指针。
具体实现如下:
class ListNode {
val: number;
next: ListNode | null;
constructor(val?: number, next?: ListNode | null) {
this.val = (val === undefined ? 0 : val);
this.next = (next === undefined ? null : next);
}
}
function oddEvenList(head: ListNode | null): ListNode | null {
if (!head || !head.next) { // 如果链表为空或只有一个节点,则直接返回原链表
return head;
}
let odd = head; // 奇数位置节点的指针
let even = head.next; // 偶数位置节点的指针
const evenHead = even; // 保存偶数位置节点的头部
while (even && even.next) {
// 重新连接奇数位置和偶数位置的节点
odd.next = even.next; // 奇数位置节点的下一个指向当前偶数位置节点的下一个
odd = odd.next; // 奇数位置指针向后移动至新的奇数位置节点
even.next = odd.next; // 偶数位置节点的下一个指向当前奇数位置节点的下一个
even = even.next; // 偶数位置指针向后移动至新的偶数位置节点
}
odd.next = evenHead; // 将奇数位置节点的末尾指向偶数位置节点的头部
return head; // 返回处理后的链表
}
复杂度分析
- 时间复杂度:O(n),其中 n 是链表的长度。需要遍历整个链表一次。
- 空间复杂度:O(1)。只需要常数级别的额外空间来存储指针。
总结
本题中,我们使用了两个指针 odd 和 even 分别指向奇数节点和偶数节点的位置,并通过移动指针将节点添加到对应的奇数或偶数链表的末尾。最后将奇数链表的尾部指向偶数链表的头部,完成了节点的重排列。
这种解法时间复杂度为 O(n),空间复杂度为 O(1),非常高效。
如果你有其他的解题思路或优化,请随时分享。