转载请注明:http://blog.csdn.net/ict2014/article/details/17510945
原题如下:
题目解析:
这道题目的意思“给定一个单链表,原地修改链表的顺序,修改的规则为0->n->2->n-1。。。。”。
最简单并且直观的做法就是:
1、将链表从中间断开
2、后面链表反转
3、两个链表进行合并
题目代码:
/**
* 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){
return;
}
int list_length = GetLength(head);
if(list_length < 3){
return;
}
ListNode* head2;
//split list into two equal(or greater than one) lists
SplitListInMiddle(head, head2, list_length);
//reverse the second list
ReverseList(head2);
//combine two lists
CombineTwoList(head, head2, list_length);
}
//calculate the length of list
int GetLength(ListNode* head){
if(head == NULL){
return 0;
}
int length = 0;
while(head != NULL){
++length;
head = head->next;
}
return length;
}
//reverse the list in place
void ReverseList(ListNode* &head){
if(head == NULL){
return;
}
ListNode* reverse_head;
ListNode* pre= NULL;
ListNode* p = head, *next;
while(p != NULL){
next = p->next;
if(next == NULL){
reverse_head = p;
}
p->next = pre;
pre = p;
p = next;
}
head = reverse_head;
}
//split the list into two equal(or greater than one) sub-lists
//if length is odd, store the middle node
void SplitListInMiddle(ListNode* head,
ListNode* &head2,
const int& length){
int sublist_length = length >> 1;
ListNode* pre;
while(sublist_length--){
pre = head;
head = head->next;
}
head2 = head;
if(length & 1 == 1){
head2 = head->next;
head->next = NULL;
}else{
pre->next = NULL;
}
}
//combine two equal length lists into one list
void CombineTwoList(ListNode* head,
ListNode* head2,
const int& length){
int sublist_length = length >> 1;
ListNode* next1, *next2;
while(sublist_length--){
next1 = head->next;
next2 = head2->next;
head->next = head2;
head2->next = next1;
head = next1;
head2 = next2;
}
}
};
时间复杂度分析:总共扫描链表共3次,求链表长度1次,切割链表0.5次,反转链表0.5次,合并链表1次。如果链表的长度为n,算法时间复杂度为O(3n).为了更加简洁,可以省略求长度的1次,最优的时候是O(2n),此时代码不如上述代码简洁可观。