24.两两交换链表中的节点
思路一:暴力解
由于头节点会变化,所以需要设置虚拟头节点;接下来,两两一组进行交换,需要记录上一组的尾指针,需要判断后面的节点是不是null
//时间复杂度:O(n) 每个元素遍历一次
//空间复杂度:O(1)
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* fakeNode = new ListNode();
fakeNode->next = head;
ListNode *oddNode = head; //奇数节点
ListNode *evenNode = head==nullptr? nullptr:head->next; //偶数节点
ListNode *last = fakeNode;//上一组的尾节点
while(oddNode && evenNode)
{
oddNode->next = evenNode->next; //奇数节点next指向偶数节点的后一个节点
evenNode->next = oddNode;//偶数节点next指向奇数节点
last->next=evenNode;//上一组的尾节点指向这一组的头节点
last=oddNode;//尾节点更换
if(oddNode->next==nullptr)
break;
oddNode = oddNode->next;//奇数指针指向更换
if(oddNode->next ==nullptr)
break;
evenNode = oddNode->next;//偶数节点指向更换
}
head = fakeNode->next;
delete(fakeNode);
return head;
}
};
思路一优化:
初始时,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;
}
};
cur移动两位,准备下一轮交换
}
return dummyHead->next;
}
};