一、题目描述
原题链接:https://leetcode.cn/problems/swap-nodes-in-pairs/comments/
题目描述:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
二、解题
方法1:迭代(哨兵位)
思路分析:
这道题目要是没有使用哨兵位的话,会写的十分复杂。首先我们知道要两个两个地翻转链表(不能交换链表中的值),需要先知道这两个结点的前一个结点(如需翻转cur和last,则需要prev)
具体操作为last->next=cur,prev->next=last,cur应该指向NULL但是我们发现此时找不到了,所以在操作last->next之前我们应该先保存last->next(struct ListNode*tmp=last-》next),即cur->next=tmp。
但是在翻转头两个结点的时候就会出现问题,因为此时没有头结点的前一个结点,所以这个时候就需要一个哨兵位了,不然头两个就要额外操作,写起来就十分麻烦了。
哨兵位还有另外一个好处,就是dummyhead的next就是翻转完需要返回的头结点,而没有哨兵位就需要额外记录一下head->next,最后再返回,有点麻烦。
至此,总体的思路就有了,就是创建dummyhead,然后两个两个翻转,不断迭代,那么迭代的条件是什么呢?当链表有偶数个的时候所有的结点都参与翻转,但是当链表有奇数个的时候最后一个结点就不参与翻转,所以迭代结束的条件就是prev或者cur或者last为空了,即while(prev&&cur&&last),这里仍有一个小细节需要注意,就是cur需要写在last之前,不然可能会出现空指针的解引用,因为cur比last前一个位置。
有了思路,写起来也就行云流水啦。
代码实现:
struct ListNode* swapPairs(struct ListNode* head){
//使用双指针避免使用中间变量
typedef struct ListNode ListNode;
ListNode *dummyhead = (ListNode *)malloc(sizeof(ListNode));
dummyhead->next = head;
ListNode* prev = dummyhead;
ListNode* cur = dummyhead->next;
while(prev && cur && cur->next )
{
prev->next = cur->next;
cur->next = prev->next->next;
prev->next->next = cur;
prev = cur;
cur = prev->next;
}
return dummyhead->next;
}
总结
总的来说这道题不算很难,但十分考验我们对链表的基础操作,以及对哨兵位的使用,相信对每个人都会有所帮助。
希望大家多多支持,我也会继续输出我的编程知识的!