注意事项:
要想节点两两交换节点,一定要让一个指针指向反转两个节点的前一个节点;
使用虚拟头结点解此题,程序实现分为遍历和交换;
cur指向头结点,如果链表的节点数为奇数,cur->next->next=NULL时,遍历结束;若链表的节点数为偶数,cur->next=NULL,遍历结束。
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 个结点 - 力扣(LeetCode)
关键:找到倒数第n个节点
注意事项:
要想删除当前节点,操作指针要指向当前节点的前一节点;
倒数第n个节点的寻找,使用虚拟头结点的技巧和双指针法;定义一个快指针和一个慢指针,让快指针先移动n步,然后快慢指针同时移动,直到快指针指向空节点,那么慢指针指向了要删除的节点;由注意事项1可得,应让快指针移动n+1步,然后快慢指针同时移动,这样慢指针就指向了要删除节点的前一个节点
需要对删除节点进行释放
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(head == nullptr || head->next == nullptr) return NULL;
ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* fast = head;
ListNode* slow = dummyhead;
for(int i = 0; i<n; i++)
{
fast = fast->next;
}
while(fast)
{
fast = fast->next;
slow = slow->next;
} //节点释放与删除操作
ListNode* temp = slow->next;
slow->next = temp->next;
delete temp;
return dummyhead->next;
}
};
注意:此题是求解两个链表交点节点的指针,交点不是数值相等,而是指针相等!
![](https://img-blog.csdnimg.cn/img_convert/2e75909a91ca33fdaf52dc75e58afd84.png)
求出两个链表的长度,并求出两个链表的差值,然后让curA移动到和curB末尾对齐的位置;
![](https://img-blog.csdnimg.cn/img_convert/3a3ecc23290fb38bcc5b37103df79c0a.png)
比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA==curB,则找到交点;否则返回空指针。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0, lenB = 0;
while (curA != NULL) { // 求链表A的长度
lenA++;
curA = curA->next;
}
while (curB != NULL) { // 求链表B的长度
lenB++;
curB = curB->next;
}
curA = headA;
curB = headB;
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
swap (lenA, lenB);
swap (curA, curB);
}
// 求长度差
int gap = lenA - lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while (gap--) {
curA = curA->next;
}
// 遍历curA 和 curB,遇到相同则直接返回
while (curA != NULL) {
if (curA == curB) {
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
使用快慢指针法解此题;
第一步:判断列表是否有环;分别定义fast和slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果fast和slow指针在途中相遇,说明这个链表有环;
第二步:如果有环,如何找到这个环的入口;
![](https://img-blog.csdnimg.cn/img_convert/47dce2b1f1260286be7e1014b26e4bf9.png)
相遇时,slow指针走过的节点数为x+y,fast指针走过的节点数为x+y+n(y+z);因为fast指针是一次走两个节点,slow指针一次走一个节点,所以2*(x+y)=x+y+n(y+z);若要找到环形入口节点,那么x表示头结点到环形入口的距离,整理得x=(n-1)(y+z)+z;当n=1时,x = z;从头结点出发一个指针,从相遇节点出发一个指针,这两个节点每次只走一个节点,那么当这两个指针相遇的时候就是环形入口的节点。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast!=NULL && fast->next!=NULL) //判断是否有环
{
fast = fast->next->next;
slow = slow->next;
if(slow == fast) //寻找环的入口
{
ListNode* index1 = fast;
ListNode* index2 = head;
while(index1!=index2)
{
index1 = index1->next;
index2 = index2->next;
}
return index2;
}
}
return NULL;
}
};