NC133 链表的奇偶重排
题目描述
给定一个单链表,请设定一个函数,将链表的奇数位节点和偶数位节点分别放在一起,重排后输出。 注意是节点的编号而非节点的数值。
1. 使用2个队列
使用两个队列分别记录下链表的奇数节点,偶数节点,再遍历链表,依次出队列装回去,只改变value即可。
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* oddEvenList(ListNode* head) {
int i = 1;
queue<int> odd, even;
ListNode* p = head;
while (p) {
if (i&1) odd.push(p->val);
else even.push(p->val);
i++, p=p->next;
}
p = head;
// 奇数在前
while (!odd.empty()) {
int val = odd.front();
odd.pop();
p->val = val;
p = p->next;
}
// 偶数在后
while (!even.empty()) {
int val = even.front();
even.pop();
p->val = val;
p = p->next;
}
return head;
}
};
- 时间复杂度:, 遍历了一次链表,和队列,总长度均为n。
- 空间复杂度:, 维护了长度和为n的两个队列。
2. 利用链表操作,一次遍历即可(常数空间的解法)
方法一经历了2次遍历,我们可以优化它。我们定义两个头部节点odd
和even
, 分别表示“奇链表”和“偶链表”的头结点,每遍历一次,往对应链表尾部插入一个节点,最后“奇链表”的尾部指向“偶链表”的头部即可。
为了实现空间, 我们只能就地操作节点,那么对于“奇链表”,我们把每个奇数节点都指向next的next,这样就跳过了偶节点,偶数的同理,最后奇数末尾为偶数,就得到了答案。
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* oddEvenList(ListNode* head) {
if (!head || !head->next) return head;
ListNode* odd = head;
ListNode* even = head->next;
ListNode* temp = even;
while (odd->next && odd->next->next) {
// 类似于删除链表节点的操作,把偶数节点删掉
// 对应上图,就相当于1号点直接指向了3号点
odd->next = odd->next->next;
// 同理,2号点指向了4号点
even->next = even->next->next;
// 指向下一个节点,就是删除前的下2个节点
// 对应上图,就是从1号点跳到3号点
odd = odd->next;
even = even->next;
}
odd->next = temp;
return head;
}
};
- 时间复杂度:, 遍历了一次链表,总长度为n。
- 空间复杂度:,常数个变量。