🔥博客主页: 我要成为C++领域大神
🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】
❤️感谢大家点赞👍收藏⭐评论✍️
本博客致力于分享知识,欢迎大家共同学习和交流。
给定一个单链表 L
的头节点 head
,单链表 L
表示为:
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入:head = [1,2,3,4] 输出:[1,4,2,3]
示例 2:
输入:head = [1,2,3,4,5] 输出:[1,5,2,4,3]
方法一:折半翻转再重连
折半拆分链表+倒置链表+合并链表
链表长度为奇数和偶数时,需要拆分的节点位置不同。因此需要判断长度奇偶。
int half=nLength%2==0?nLength/2:(nLength+1)/2;
流程:
1、遍历链表,记录长度nLength
2、根据长度是奇数还是偶数,求得中间折半断开位置int half=nLength%2==0?nLength/2:(nLength+1)/2;
3、拆分链表。while循环,每次循环迭代中,都会将 half 减1,以确保循环会在遍历到链表一半的位置时结束。找到其一半位置的节点,将其后面的节点都断开,使链表分成两个部分。
int half=nLength%2==0?nLength/2:(nLength+1)/2;
while(half>=0){
if(half==0){
pBreak=p;
break;
}
else if(half==1){
struct ListNode* pNext=p->next;
p->next=NULL;
p=pNext;
}
else{
p=p->next;
}
half--;
}
4、将后一半位置的链表进行倒置。
ReverseList:三个指针:断开、改向、移动
struct ListNode* reverseList(struct ListNode* head) {
if (head == NULL)
return NULL;
struct ListNode* p1 = NULL;
struct ListNode* p2 = head;
struct ListNode* p3 = p2->next;
while (p3) {
p2->next = p1;
p1 = p2;
p2 = p3;
p3 = p3->next;
}
p2->next = p1;
return p2;
}
5、合并原来的一半链表和倒置之后的一半链表。(MergeList:三个指针)
struct ListNode* mergeList(struct ListNode* head1, struct ListNode* head2) {
if (head1 == NULL)
return head2;
if (head2 == NULL)
return head1;
struct ListNode* head = head1;
struct ListNode* p = head1;
head1 = head1->next;
while (head1 && head2) {
p->next = head2;
p = head2;
head2 = head2->next;
p->next = head1;
p = head1;
head1 = head1->next;
}
if (head1 == NULL)
p->next = head2;
if (head2 == NULL)
p->next = head1;
return head;
}
方法二:折半断开入栈
流程:
1、遍历链表,记录长度nLength
2、根据长度是奇数还是偶数,求得中间折半断开位置int half=nLength%2==0?nLength/2:(nLength+1)/2;
3、拆分链表。while循环,每次循环迭代中,都会将 half 减1,以确保循环会在遍历到链表一半的位置时结束。找到其一半位置的节点,将其后面的节点都断开,使链表分成两个部分。
int half=nLength%2==0?nLength/2:(nLength+1)/2;
while(half>=0){
if(half==0){
pBreak=p;
break;
}
else if(half==1){
struct ListNode* pNext=p->next;
p->next=NULL;
p=pNext;
}
else{
p=p->next;
}
half--;
}
4、将[half,nLength]部分的链表压入栈中
stack<ListNode*> s;
while (pBreak != nullptr) {
s.push(pBreak);
pBreak = pBreak->next;
}
5、 依次将节点出栈,合并前后两部分节点
ListNode* ptr1 = head;
ListNode* ptr2 = s.top();
s.pop();
while (!s.empty()) {
ListNode* tempNode = ptr1->next;
ptr1->next = ptr2;
ptr2->next = tempNode;
ptr1 = tempNode;
ptr2 = s.top();
s.pop();
}
6、尾节点的指针域置空
ptr2->next = nullptr;