两两交换相邻节点

题目描述:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

注意:是进行节点的交换,不是单纯地交换节点中的值

比如链表为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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值