给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
题目其实没有说清楚,两两交换的字眼容易误以为数据一定为偶数个,但根据测试结果来看有奇数的情况,多出来的那个不需要交换。也就是两个一组进行交换,最后无法构成两个的则不操作。
由于是分别逆置一组中的两个元素,并且后面交换后的表影响着前面交换后靠后那个元素的指针,所以利用栈先处理后面的元素,将交换完毕的靠前的节点存下来为相邻的前一组提供后继。
具体流程:
/**
* 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) {
stack<ListNode*> st;
ListNode* before = NULL; //上一组交换后的节点头
ListNode *p, *q;
int cnt = 0;
while (head) {
st.push(head);
head=head->next;
cnt++;
}
if (cnt & 1) {
before = st.top();
st.pop();
}
while (!st.empty()) {
p = st.top(); st.pop();
q = st.top(); st.pop();
p->next = q;
q->next = before;
before = p;
}
return before;
}
};
本题可以利用递归的形式省去栈的数据结构,代码也比较易写且简洁。而非递归的方式也有不需要利用栈的,具体移步代码。
/**
* 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 == NULL || head->next == NULL) {
return head;
}
ListNode* nxt = head->next;
head->next = swapPairs(nxt->next);
nxt->next = head;
return nxt;
}
};
大致思路就是每次处理完一组交换后保存一个本组的后一个节点指针,当下一组交换完毕后则更新这个节点的后继指针的指向,并且更新这个节点指针
大致流程:
/**
* 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 *lhead = new ListNode();
lhead->next = head;
ListNode *pre = lhead, *p, *q;
while (head && head->next) {
p = head->next;
pre->next = p;
head->next = p->next;
p->next = head;
pre = head;
head = head->next;
}
return lhead->next;
}
};