解题思路:
题目已经强调需要进行的是链表结点的交换而非结点内值的交换,所以需要一步步的改变指针的指向。
指针题目,首先都建立一个虚拟头节点,这样做的好处是在之后处理每结点时,不用区分头节点和非头节点,操作上会简单一点。
回到这道题,毫无疑问是用循环来遍历每一个结点,所以需要先判断循环终止的条件,当结点个数为单数,则最后一个结点不需要进行交换;若为双数,则当指针指向NULL时结束
每一次遍历,需要关联到四个指针,前一个结点 、交换的两个结点 、后一个结点。为了防止改变指针后,在其之后的结点会“失联”,我们需要使用一个临时指针来记录 交换指针1 、后一个结点
交换的顺序:前一个结点指针 - > 交换结点2 - > 交换结点1(temp指针记录)- > 后一个结点(temp2指针记录)
交换结束后将cur指针往后移动两位,重复操作。
附上ac代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
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;
cur -> next -> next = temp;
temp -> next = temp1;
cur = cur -> next -> next;
}
return DummyHead->next;
}
};
19.删除链表的倒数第N个节点
解题思路:
第一想法是遍历到最后一个结点,然后往前数n-1个,但意识到这是单链表,没法回退,只好放弃。
看完题解,意识到可以用双指针的方法:
定义快慢指针,快指针先行n步,慢指针再出发同时向前,注意:此时两指针相差n步 当快指针指向NULL时可以得知从NULL的前一个结点,即尾结点开始倒数第n个节点的就是慢指针所指的结点,又因为进行删除操作时需要再前一个指针上进行,故再上一步,就让快指针多走一步,这样最后慢指针所指的就是倒数n+1个结点。
附上ac代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *dummyHead = new ListNode(0);
dummyHead -> next = head;
ListNode *slow = dummyHead;
ListNode *fast = dummyHead;
while(n-- && fast != NULL){
fast = fast -> next;
}
fast = fast -> next;
while(fast != NULL){
fast = fast -> next;
slow = slow -> next;
}
ListNode *q = slow -> next;
slow -> next = slow -> next -> next;
delete q;
return dummyHead -> next;
}
};