链表面试题
我也不知道该叫什么.就叫 链表折叠 吧
题目:
给一个单链表,形如
1 2 3 4 5
变成
1 5 2 4 3
算法复杂度要求为O(n)
思路:
- 先把后半部分反转过来,
- 然后把后半部分 和 前半部分 合并.
用到的知识点:
- 构建单链表
- 链表反转
- 链表合并(这个其实相当于插入了一个节点)
- 遍历单链表
# include <bits/stdc++.h>
using namespace std;
struct node{
int x;
struct node * next;
node(int a,struct node * b):x(a),next(b) {
}
};
node * head;
//输入单链表
void input(int n)
{
int x;
node * cur;
for( int i = 0;i < n;i++)
{
scanf("%d",&x);
node *tem = new node(x,NULL);
if(head == NULL)
{
head = tem;
cur = head;
}else{
cur->next = tem;
cur = cur->next;
}
}
}
//遍历单链表
void show(node * p)
{
printf("\n=============================\n");
while(p != NULL)
{
printf("%d ",p->x);
p = p->next;
}
printf("\n");
}
// 整体反转
void reverse(node * p)
{
node * cur = NULL;
node * tem ;
while(p != NULL)
{
tem = p->next;
p->next = cur;
cur = p;
p = tem;
}
head = cur;
}
//链表折叠
void halfReverse(node * phead)
{
node * p = phead;
//链表的长度
int len = 0;
while(p != NULL)
{
len++;
p = p-> next;
}
if(len == 1) return;
int mid = len / 2;
p = phead;
int cnt = 0;
//找到链表一半的位置
while(p != NULL){
cnt++;
if(cnt == mid) break;
p = p->next;
}
node * halfHead = p;
//反转完成后,cur存放后半部分链表的起点
node * cur = NULL;
node * tem;
p = p->next;
while(p != NULL){
tem = p->next;
p->next = cur;
cur = p;
p = tem;
}
halfHead->next = NULL;
p = phead;
node * curTem;
while(p != NULL){
tem = p->next;
p->next = cur;
curTem = cur->next;
//处理奇数个节点的情况
if(tem == NULL && len % 2){
cur->next = curTem;
}else{
cur->next = tem;
}
p = tem;
cur = curTem;
}
}
int main()
{
int n;
scanf("%d",&n);
//输入n个整数
input(n);
//遍历单链表
show(head);
//折叠链表 1 2 3 4 5 变成 1 5 2 4 3
halfReverse(head);
show(head);
return 0;
}