题目:
给定一个单链表 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.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reorder-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
分为三步:
(1)算出链表长度,从中间断开,变成2个链表
(2)后半段链表反转,输出新的head即原来的tail
(3)把2个链表交叉串起来。
代码:
int GetLength(ListNode *p)//获取链表长度
{
int ans=0;
while(p)
{
ans++;
p=p->next;
}
return ans;
}
ListNode * Reverse(ListNode *p)//链表反转,返回新的head
{
if(p==NULL)return p;
ListNode * q1;
ListNode * q2;
q1=p->next, p->next=NULL;
while(q1)
{
q2=q1->next, q1->next=p, p=q1, q1=q2;
}
return p;
}
class Solution {
public:
void reorderList(ListNode* head) {
if(head==NULL)return;
int length=GetLength(head);
length=(length-1)/2;
ListNode* p=head;
while(length--)p=p->next;
ListNode*q=p->next;
p->next=NULL; //链表割开
q=Reverse(q);//后半段反转
p=head;
ListNode* pnext,*qnext;
while(q)
{
pnext=p->next, qnext=q->next;
p->next=q, q->next=pnext;
p=pnext, q=qnext;
}
}
};
做题时候调试用的测试代码:
int main()
{
ListNode *p1=new ListNode(1);
ListNode *p2=new ListNode(2);
ListNode *p3=new ListNode(3);
ListNode *p4=new ListNode(4);
p1->next=p2,p2->next=p3,p3->next=p4,p4->next=NULL;
Solution s;
s.reorderList(p1);
cout<<p1->val<<p2->val<<p3->val<<p4->val<<endl;
while(p1)
{
cout<<p1->val;
p1=p1->next;
}
return 0;
}
输出:
1234
1423
PS:可以看出修改链表的节点存储的数值,和修改链表的链接,是不一样的。这也是题目要求的做法。