题1:
指路:LeetCode24 两两交换链表中的节点
思路与代码:
我们在头节点前定义一个虚拟头节点,并定义一个cur指针指向它,使cur指针能操作后面两个节点,当要交换的两个节点都不为零的时候,定义一个临时节点指向要交换的两个节点的前一个节点(简称操作中前节点),再定义一个临时指针存储操作中后节点的下一个节点(而因为我们定义的cur指针可以指向后两个指针,所以操作中后节点可以用cur间接指向)。代码如下:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyhead = new ListNode(0); // 虚拟头节点
dummyhead->next = head;
ListNode* cur = dummyhead;
while (cur->next != NULL && cur->next->next != NULL) {
ListNode* temp = cur->next; // 临时节点指向两两交换中的前一个节点
ListNode* temp1 = cur->next->next->next; // 指向两两交换的后一个节点的下一个节点
cur->next = cur->next->next; // 1.cur->next指向两两交换的后一个节点
cur->next->next = temp; // 2.让两两交换的后一个节点指向原来的前一个节点
cur->next->next->next = temp1; // 3.让两两交换后的后一个节点指向下一对交换的双节点中的前一个节点
cur = cur->next->next; // cur指针后移两位
}
ListNode* ans = dummyhead->next;
delete dummyhead;
return ans;
}
};
题2:
指路:LeetCode19 删除链表的倒数第N个节点
思路与代码:
本题值得思考的地方在于如何找到应该删除的倒数第n个节点。这里我们定义快慢指针进行操作,让快指针先走n步,之后快慢指针一起移动,等快指针移动到末尾空的时候,慢指针到达的地方就是链表倒数第n个节点的位置。代码如下:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* fast = dummyhead;
ListNode* slow = dummyhead;
n++;
while(n-- && fast!=NULL) {
fast = fast->next; // 快指针先走n+1步
}
while(fast != NULL) {
fast = fast->next; // 快指针到尾节点
slow = slow->next; // 同时慢指针跟随快指针一起走
}
slow->next = slow->next->next; // 慢指针的下一个节点指向下一个节点的下一个节点
return dummyhead->next;
}
};
补充:n自增的操作是因为,我们在删除元素时应该让这个元素的上一个指针指向它的下一个指针,所以要找到该元素的上一个指针,因此让快指针多走一步,慢指针少走一步达到效果。