操作的指针cur一定要指向要反转的两个节点的前一个节点
判断停止的条件:要翻转的节点列表的个数如果为偶数个那么cur->next为空则停止,如果为奇数个那么cur->next->next为空则停止,空列表的话个数为0也符合偶数个的特点
while(cur->next != nullptr && cur->next->next != nullptr)
用与而不用或的原因是:如果为"或"那奇数的时候还会循环 并且cur->next != nullptr必须写在前面因为如果写在后面cur->next->next会报错 因为万一cur->next为空他则没有next的成员
并且循环中需要临时保存需要交换的第一个节点和下面依次循环中需要交换的第一个节点。
这道题目一定要结合图来写 要不然很容易会晕
下面是完整的代码:
/**
* 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,head);
ListNode* cur = dummyHead;
while (cur->next && cur->next->next) {
ListNode* temp = cur->next;
ListNode* temp1 = cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = temp;
cur->next->next->next = temp1;
cur = cur->next->next;
}
return dummyHead->next;
}
};
一上来的想法是将倒数第n个节点转换成从1开始的正数的第几个 因此首先得计算一下节点的个数 count然后判断倒数等于正数的第几个 如果是倒数第一个就是正数的第n个 因此转换成正数的公式是number = count - n + 1 但是这样执行while(n--) {cur = cur->next;}后cur会移动到要删除的节点上 因此这里需要提前n-1 再进行n-- 也可以直接令number = count - n 这样cur就会移动到要删除的节点的前一个节点上了。完整的代码如下:
/**
* 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,head);
ListNode* cur = dummyHead;
int count = 0;
while (cur->next) {
count++;
cur = cur->next;
}
cur = dummyHead;
int number = count - n;
while (number--) {
cur = cur->next;
}
cur->next = cur->next->next;
return dummyHead->next;
}
};
代码随想录里的方法,是双指针思路是这样的 如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。
fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图:
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; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
while (fast != NULL) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
// ListNode *tmp = slow->next; C++释放内存的逻辑
// slow->next = tmp->next;
// delete tmp;
return dummyHead->next;
}
};
简单来说,就是求两个链表交点节点的指针。 这里同学们要注意,交点不是数值相等,而是指针相等。
题目还算简单暴力循环即可解决
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* temp = headB;
while (headA) {
while (headB) {
if (headA == headB) {
return headA;
}
else {
headB = headB->next;
}
}
headA = headA->next;
headB = temp;
}
return NULL;
}
};
题目很有难度 自己想肯定想不出来复习的时候直接视频复习就行了
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
if (slow == fast) {
ListNode* index1 = fast;
ListNode* index2 = head;
while (index1 != index2) {
index1 = index1->next;
index2 = index2->next;
}
return index2; // 返回环的入口
}
}
return NULL;
}
};