赞
踩
题目描述:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
注意:是进行节点的交换,不是单纯地交换节点中的值
比如链表为1->2->3->4,交换后变成2->1->4->3。
首先链表定义:
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
分析:首先需要设置一个虚拟头节点,因为交换两个节点的时候,需要操作两个节点前的节点。由于第一个节点前面没有节点,所以需要设置虚拟头节点。
ListNode *dummyhead=new ListNode(0);
dummyhead->next=head;
操作步骤:
首先定义一个动态的节点ListNode *cur=dummyhead。该节点意义为交换两个节点的前一个节点,通过对这个节点进行操作来交换后面两个节点。
所以循环停止的条件有两个:
1、如果链表长度为偶数时,最终cur会落到最后一个节点,此时的终止条件是cur->next!=nullptr
2、如果链表长度为奇数时,最终cur会落到倒数第二个节点,此时的终止条件是cur->next->next!=nullptr,最后一个元素不用管。
来看一次交换中的步骤:
dummyhead->1->2->3->4需要变成dummyhead->2->1>3>4
step1:将dummyhead指向2,此时链接1处断开了
step2:将2指向1,此时链接3断开了
此时,在第一步中,由于链接1断开了,无法指向1,所以要提前保存1的位置。
step3:将1指向3,此时2断开了
此时,在第二步中,由于链接3断开了,无法指向3,所以需要提前保存3的位置
ListNode *tmp1=cur->next->next->next;//保存3的位置
ListNode *tmp2=cur->next;//保存1的位置
总结:怎么看提前保存哪些?画图来看,连一个,断一个,如果后续需要再用的话,就提前保存。
注意:cur的后面的节点在过程中是不断变化的,因为连一个断一个,后续都在发生变化。
step1:cur->next=cur->next->next;
step2:此时2是连接在cur的下一个的。所以步骤2应该为cur->next->next=tmp2;而不是cur->next->next->next=tmp2。cur->next->next->next=tmp2是没有进行步骤1的写法。
step3:此时dummyhead后面是连接的2和1。所以1代表的是cur->next->next。1要连接3的话是cur->next->next->next=tmp1。
进行了这三步后,链表就变成了 dummyhead->2->1->3->4。
为了进行后续的交换,把cur移动到3的位置。即cur=cur->next->next。
最终循环结束,返回虚拟头节点的下一个节点。为什么不返回head?因为head交换到第二个位置去了。如果返回head,那结果就为交换后第二个节点到最后,会损失交换后第一个节点的数据。比如,原链表为1->2->3->4,返回head就为1->4->3,head只要不在代码中进行修改,指的就是数值为1的那个节点。所以要返回虚拟头结点的下一个节点。
完整代码如下:
最后一行的代码修改为return dummyhead->next。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。