Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You may not modify the values in the list's nodes, only nodes itself may be changed.
Example 1:
Given 1->2->3->4, reorder it to 1->4->2->3.
Example 2:
Given 1->2->3->4->5, reorder it to 1->5->2->4->3.
题目链接:https://leetcode-cn.com/problems/reorder-list/
解题过程
刚开始题意理解错,样例没看清,理解成了将偶数元素链逆序后插回奇数元素链,类似:
1->2->3->4变为1->4->3->2
1->2->3->4->5变为1->4->3->2->5
(虽然题意理解错了,但是回头想代码还是有意义的)
思路是:将奇偶拆成两个链,拆的同时对偶数链做逆序,然后再把偶数链插回奇数链。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
if (head==NULL ||head->next==NULL ||head->next->next==NULL) return;
auto odd = head, even = head->next, idx = head->next->next;
even->next = NULL;
while(idx!=NULL){
odd->next = idx;
odd = odd->next;
idx = idx->next;
if(idx!=NULL){
auto tmp = idx->next;
idx->next = even;
even = idx;
idx = tmp;
}
}
odd->next = NULL;
odd = head;
while(even!=NULL){
auto tmp = even->next;
even->next = odd->next;
odd->next = even;
odd = even->next;
even = tmp;
}
return;
}
};
发现理解错后,新思路总体没有太大差别,都是:拆链,逆序,插回。
区别在于本题是需要拆成前后两个链,可用快慢指针完成;逆序操作需要单独完成。
其他操作都一样,代码少做修改即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode* head) {
if (head==NULL ||head->next==NULL ||head->next->next==NULL) return;
auto l = head, r = head;
while(r->next){
r = r->next;
if(r->next){
r = r->next;
l = l->next;
}
}
r = l->next;
auto nxt = r->next;
while(nxt){
auto last = r;
r = nxt;
nxt = r->next;
r->next = last;
}
l->next->next = NULL;
l->next = NULL;
l = head;
while(r){
nxt = r->next;
r->next = l->next;
l->next = r;
l = r->next;
r =nxt;
}
return;
}
};