文|Seraph
01 | 问题
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
02 |解题
初解:
这里思路就是通过交换指向指针来变动两两前后节点的顺序。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head==nullptr)
return nullptr;
ListNode *cur = head;
ListNode *next = cur->next;
ListNode *result = next;
ListNode *pre = nullptr;//用来记录两两节点的前一个节点
while(next!=nullptr && cur!=nullptr)
{
cur->next = next->next;
next->next = cur;
if(pre!=nullptr)
{
pre->next = next;
}
pre = cur;
cur = cur->next;
if(cur!=nullptr)
{
next = cur->next;
}
}
return result?result:head;//判断是不是仅有一个节点。
}
};
以上解法,交换和判断有点过多。看起来有点乱。
这里可以使用一个链表常用的方法减少头结点的特殊处理逻辑。在链表前再加一个空节点就可以了。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode *pre = new ListNode(0);
pre->next = head;
ListNode *p = pre;
while(p->next!=nullptr && p->next->next!=nullptr)
{
ListNode *start = p->next;
ListNode *end = p->next->next;
start->next = end->next;
end->next = start;
p->next = end;
p = start;
}
return pre->next;
}
};
再想下,因为节点值是int的,不大,所以其实可以直接交换值,反而更简单。(后面仔细看了下,好像题目提示不能交换节点的值。。。)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head==nullptr || head->next == nullptr)
return head;
ListNode *cur = head;
ListNode *next = cur->next;
while(next!=nullptr && cur!=nullptr)
{
cur->val = cur->val ^ next->val;
next->val = cur->val ^ next->val;
cur->val = cur->val ^ next->val;
cur = cur->next->next;
if(cur != nullptr)
{
next = cur->next;
}
}
return head;
}
};
终解:
大部分链表的题,都是能使用递归了,这题也不例外。
当写递归的时候,一定不要按迭代的思想去试图屡清楚,这样会相当煎熬。
只需按如下步骤:
- 终止条件是什么?
- 假设K+1步处理好了,怎么处理K步?
- 返回值是什么?
每次写递归,写不出来,然后看别人怎么写的,都感觉自己是个傻子。而且还是心里没底,是不是完全符合题意。哈哈~,还是得多练,多想吧。。。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head==nullptr || head->next == nullptr)
return head;
ListNode *next = head->next;
head->next = swapPairs(next->next);
next->next = head;
return next;
}
};
03 | 积累知识点
- 链表处理时,为了统一处理逻辑,可以加一个空节点。
- 递归思想不要一步一步推导,只需要知道终止条件、前后推导就行。
官网链接 Leetcode No.24