一、题目描述
个人ac代码 :
class Solution { public: ListNode* swapPairs(ListNode* head) { if(!head||!(head->next))return head; ListNode *pre=head; ListNode* cur=head->next; int cnt=0; while(cur) { ListNode*tmp=cur->next;//走到这边,已经确保cur->next不为空了->防止断链 ListNode*connect=pre; cur->next=pre; pre->next=tmp; if(cnt==0)//第一次翻转->保存好头结点 head=cur; pre=tmp; if(pre==nullptr||pre->next==nullptr) break; else { cur=pre->next; connect->next=cur;//做好连接 } cnt++; } return head; } };
关键:connect指针去保存上一次翻转之后的尾结点,先连接好下一组的cur指针!!!
二、参考思路和写法:
1.参考思路:
①建议使用虚拟头结点,这样会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。
②接下来就是交换相邻两个元素了,此时一定要画图,不画图,操作多个指针很容易乱,而且要操作的先后顺序 初始时,cur指向虚拟头结点,然后进行如下三步:
相应实现代码:
class Solution { public: ListNode* swapPairs(ListNode* head) { ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点 dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作 ListNode* cur = dummyHead; while(cur->next != nullptr && cur->next->next != nullptr) { ListNode* tmp = cur->next; // 记录临时节点 ListNode* tmp1 = cur->next->next->next; // 记录临时节点 cur->next = cur->next->next; // 步骤一 cur->next->next = tmp; // 步骤二 cur->next->next->next = tmp1; // 步骤三 cur = cur->next->next; // cur移动两位,准备下一轮交换 } return dummyHead->next; } };
- 时间复杂度:O(n)
- 空间复杂度:O(1)
上述代码注意细节:
①虚拟头结点的设定dummy head
②while条件先后顺序,先判断cur->next是否为空(为空就是偶数节点,已经考虑了head=nullptr的情况),然后再去判断cur->next->next,防止空指针报错
③注意需要两个指针来记录临时节点,如上图,(1)在dummyhead指向2之后,就会找不到1,所以要提前保存一下1节点的位置(2)在2指向1之后,就会断链,所以要提前保存3节点的位置。
2.补充C语言的递归&迭代方法:
//递归版本
struct ListNode* swapPairs(struct ListNode* head){
//递归结束条件:头节点不存在或头节点的下一个节点不存在。此时不需要交换,直接返回head
if(!head || !head->next)
return head;
//创建一个节点指针类型保存头结点下一个节点
struct ListNode *newHead = head->next;
//更改头结点+2位节点后的值,并将头结点的next指针指向这个更改过的list
head->next = swapPairs(newHead->next);
//将新的头结点的next指针指向老的头节点
newHead->next = head;
return newHead;
}
//迭代版本
struct ListNode* swapPairs(struct ListNode* head){
//使用双指针避免使用中间变量
typedef struct ListNode ListNode;
ListNode *fakehead = (ListNode *)malloc(sizeof(ListNode));
fakehead->next = head;
ListNode* right = fakehead->next;
ListNode* left = fakehead;
while(left && right && right->next ){
left->next = right->next;
right->next = left->next->next;
left->next->next = right;
left = right;
right = left->next;
}
return fakehead->next;
}