问题描述 :
给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
给定链表 1->2->3->4, 重新排列为 1->4->2->3.
示例 2:
给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.
可使用以下代码,完成其中的reorderList函数,其中形参head指向无头结点单链表。
#include
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode() : val(0), next(NULL) {}
ListNode(int x) : val(x), next(NULL) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution
{
public:
void reorderList(ListNode* head)
{
//填充本函数完成功能
}
};
ListNode *createByTail()
{
ListNode *head;
ListNode *p1,*p2;
int n=0,num;
int len;
cin>>len;
head=NULL;
while(n<len && cin>>num)
{
p1=new ListNode(num);
n=n+1;
if(n==1)
head=p1;
else
p2->next=p1;
p2=p1;
}
return head;
}
void displayLink(ListNode *head)
{
ListNode *p;
p=head;
cout<<"head-->";
while(p!= NULL)
{
cout<<p->val<<"-->";
p=p->next;
}
cout<<"tail\n";
}
int main()
{
ListNode* head = createByTail();
Solution().reorderList(head);
displayLink(head);
return 0;
}
输入说明 :
首先输入链表长度len,然后输入len个整数,以空格分隔。
输出说明 :
输出格式见范例
输入范例 :
5
1 2 3 4 5
输出范例 :
head–>1–>5–>2–>4–>3–>tail
/*
给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
给定链表 1->2->3->4, 重新排列为 1->4->2->3.
示例 2:
给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.
算法思想:
法一:遍历链表节点,将节点加入vector,通过索引完成重新排序,时间复杂度O(n)
法二:
1.快慢指针找到中点
2.将后半段逆置
3.将后半段插入前半段
*/
#include<iostream>
#include<vector>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode() : val(0), next(NULL) {}
ListNode(int x) : val(x), next(NULL) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution
{
public:
void reorderList(ListNode* head)
{
if(head == NULL)
{
return;
}
vector<ListNode *> node_vec;
ListNode *p = head;
//将链表节点的指针加入vector中
while(p)
{
node_vec.push_back(p);
p = p->next;
}
int i = 0,j = node_vec.size()-1;
//通过索引重新完成排序
for(;i != j; i++,j--) //当链表有奇数个节点时会从i!=j处退出循环
{
node_vec[i]->next = node_vec[j];
if(j == i+1)
{
break; //当链表有偶数个节点时会从 这里退出循环
}
node_vec[j]->next = node_vec[i+1]
}
node_vec[j]->next = NULL; //表尾结点后继为NULL
}
void reorderList2(ListNode* head){
if(head == NULL){
return ;
}
//1.快慢找到需要重排的后半部分
ListNode *slow = head;
ListNode *fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
//2.逆置后半部分链表
ListNode *p = slow->next; //后半部分的开始
ListNode *pre_node = NULL;
while(p)
{
ListNode *next = p->next; //保存p的后继
p->next = pre_node; //p指向其前驱节点
pre_node = p; //更新pre
p = next; //更新p;
}
//3.将逆置后的后半部分插入前半部分
ListNode *left = head;
ListNode *right = pre_node;
while(right)
{
ListNode *next = right->next;
right->next = left->next;
left->next = right;
right = next;
left = left->next->next;
}
}
};
ListNode *createByTail()
{
ListNode *head;
ListNode *p1,*p2;
int n=0,num;
int len;
cin>>len;
head=NULL;
while(n<len && cin>>num)
{
p1=new ListNode(num);
n=n+1;
if(n==1)
head=p1;
else
p2->next=p1;
p2=p1;
}
return head;
}
void displayLink(ListNode *head)
{
ListNode *p;
p=head;
cout<<"head-->";
while(p!= NULL)
{
cout<<p->val<<"-->";
p=p->next;
}
cout<<"tail\n";
}
int main()
{
ListNode* head = createByTail();
Solution().reorderList2(head);
displayLink(head);
return 0;
}