鏈表面試題
我也不知道該叫什麼.就叫 鏈表摺疊 吧
題目:
給一個單鏈表,形如
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;
}