地址:https://leetcode.com/problems/swap-nodes-in-pairs/
题目:
Given a linked list, swap every two adjacent nodes and return its head.
Example:
Given 1->2->3->4, you should return the list as 2->1->4->3.
Note:
- Your algorithm should use only constant extra space.
- You may not modify the values in the list’s nodes, only nodes itself may be changed.
理解:
一开始就想到了直接改val
,一看note不允许。。那就直接改喽。
为了处理链表的头,加了个头节点。用三个指针分别指向前一个,第一个和第二个节点。
修改的过程如下图所示:
注意三个指针保存了三个结点的地址,因此修改pr->next
一定要晚于让pl->next=pr->next
。
实现1:
自己的实现,不过要比别人的慢一些。
下面更新了一版。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if (!head || !head->next) return head;
ListNode* nHead = new ListNode(0);
nHead->next = head;
ListNode* pre = nHead;
ListNode *pl = pre->next, *pr = pre->next->next;
while (1) {
pl->next = pr->next;
pr->next = pl;
pre->next = pr;
if (pl->next&&pl->next->next) {
pre = pl;
pl = pre->next;
pr = pl->next;
}
else
break;
}
return nHead->next;
}
};
//后来仿照实现2修改的代码
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* pre = nullptr;
ListNode* newHead=head;
ListNode *pl = head, *pr=head;
while (pl&&pl->next) {
newHead = pl==pr ? pl->next : newHead;
pr = pl->next;
pl->next = pr->next;
pr->next = pl;
if (pre) {
pre->next = pr;
}
pre = pl;
pl = pl->next;
}
return newHead;
}
};
实现2
下面是别人的实现。
其中retval
只有第一次翻转会更新,就是新的头结点。巧妙的避免了要判断是否是头结点的情况。可能就是这里省了一点时间?
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* retval = head;
ListNode* currval = head;
ListNode* prevval = NULL;
while (currval != NULL && currval->next != NULL)
{
retval = currval == retval ? currval->next : retval;
ListNode* nextIter = currval->next->next;
currval->next->next = currval;
if (prevval != NULL)
{
prevval->next = currval->next;
}
currval->next = nextIter;
prevval = currval;
currval = nextIter;
}
return retval;
}
};
实现3:
使用了一个pointer to pointer,非常巧妙
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode **pp = &head, *a, *b;
ListNode **pp2;
while ((a = *pp) && (b = a->next)) {
a->next = b->next;
b->next = a;
*pp = b;
ListNode *tmp = a->next;
pp2 = &tmp;
pp = &(a->next);
}
return head;
}
};
分情况解释一下。
- 如果为空,或只有一个,返回的就是head;
- 不为空
- 一开始,pp指向head指针,
*pp=b
使得head发生了改变; - 再后来,pp指向的是前一个链表节点的next域,
*pp=b
完成了pre->next=pr
的工作。
- 一开始,pp指向head指针,