List--Reorder1

来源:互联网 发布:什么批发软件最好用 编辑:程序博客网 时间:2024/06/06 06:31

问题描述:有链表{L0, L1, L2, ..., Ln},重新排列后得到{L0, Ln, L1, Ln-1...}。

约束条件:空间复杂度S(1),只能改变Node* next指针。

备注:        微软2014笔试最后一题。


思路一:遍历链表,每次遍历找到链表末端的节点,将其插入最终的位置。此方法时间复杂度O(n^2)。


思路二:第一趟遍历统计链表长度;第二趟遍历找到中间位置的节点;第三趟遍历将后半截链表的节点倒置;第四趟将后半截链表的节点插入前半截链表。每一趟都是单重循环,故时间复杂度为O(n)。

#include<iostream>using namespace std;class Node{public:int index;Node* next;Node(int i) : index(i), next(NULL){}};//输出链表void print(Node* ptr){while(ptr){cout << ptr->index << " ";ptr = ptr->next;}cout << endl;}void list_reorder(Node* head){if(NULL == head || NULL == head->next)return;Node* p = NULL;Node* q = NULL;Node* r = NULL;int length = 0;int index = 0;//第一趟遍历统计链表长度p = head;while(p){++length;p = p->next;}//第二趟遍历找到链表中间节点p = head;while(index++ != length / 2)p = p->next;//第三趟遍历将后半截链表倒置q = p->next;if(q)r = q->next;p->next = NULL;while(q){q->next = p;p = q;q = r;if(r)r = r->next;}//第四趟遍历将后半截链表的节点插入前半截链表q = p;p = head;r = p->next;while(true){p->next = q;p = r;if(NULL == (r = q->next))break;q->next = p;q = r;if(NULL == (r = p->next))break;}}void main(){int N = 9;Node* head = NULL;Node* ptr = NULL;for(int i = 0; i < N; ++i){if(NULL == head){head = new Node(i);ptr = head;}else{ptr->next = new Node(i);ptr = ptr->next;}}print(head);list_reorder(head);print(head);while(head){ptr = head->next;delete head;head = ptr;}}