LeetCode24. 两两交换链表中的节点
注意:交换的时候不是交换两个节点中的值,而是交换物理地址的顺序。
在进行循环时:若节点个数为偶数,需要判断cur->next是否为空;若节点个数为奇数,需要判断cur->next->next是否为空;
循环条件顺序不能写乱:若先进行cur->next->next != NULL判断,那么如果cur->next为空,那么该语句就会报错(空指针异常错误),无法进行下去。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
//定义虚拟头结点
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* cur = dummyHead;
//循环条件注意:若节点个数为偶数,需要判断cur->next是否为空;
//若节点个数是奇数,需要判断cur->next->next是否为空;
//循环顺序不能写乱,必须先判断cur->next再判断cur->next->next,否则容易发生空指针异常;
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;
cur->next->next->next = temp1;
//更新cur,为下一轮交换做准备
cur = cur->next->next;
}
return dummyHead->next;
}
};
LeetCode19.删除链表的倒数第N个节点
分析:这题的重点是正序找到要删除的节点的前一个节点。倒数第n个节点,和dummhead节点相差的距离,与正着数第n个节点 ,和尾部NULL距离相同。
如图所示,定义两个指针fast和slow,让fast先走n+1步。
fast此时到D节点的位置。然后slow与fast同步走,直到fast = NULL。此时slow指向要删除节点的前一个节点。此时进行删除操作。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* fast = dummyHead;
ListNode* slow = dummyHead;
//先让fast走n+1步
while(n-- && fast != NULL){
fast = fast->next;
}
fast = fast->next;
//开始让fast和slow一起走
while(fast != NULL){
fast = fast->next;
slow = slow->next;
}
ListNode* temp = slow->next;
slow->next = slow->next->next;
delete temp;
temp = NULL;
return dummyHead->next;
}
};
LeetCode 160.链表相交
注:链表相交:指的是相同位置的指针指向的值相等;相当于是对两个链表相同位置进行比较。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0;
int lenB = 0;
//分别获得链表的长度
while(curA != NULL){
curA = curA->next;
lenA++;
}
while(curB != NULL){
curB = curB->next;
lenB++;
}
//重新令curA和curB分别指向A链表和B链表的头节点
curA = headA;
curB = headB;
//令lenA表示长链表
if(lenB > lenA){
swap(lenB,lenA);
swap(curB,curA);
}
//计算两个链表之间的长度差
int gap = lenA-lenB;
//两个链表尾部对其,将指针curA和curB调整到同一个位置
while(gap--){
curA = curA->next;
}
//进行交点的判断
while(curB != NULL){
if(curA == curB) return curA;
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
LeetCode 142.环形链表II
(采用快慢指针方法)
分析:本题有两个重点,(1)找到相遇的点,即判断是否有环;(2)找到环入口;
(1)分别设置两个指针fast和slow,fast指针每次走两步,slow指针每次走一步,当存在环的时候,当两个指针都进入环内,fast指针和slow指针会相遇。
(2)x:表示head节点到入环节点之间的节点个数;
y:表示入环节点到相遇节点之间的节点个数;
z:表示相遇节点到入环节点之间的个数;
slow指针走的节点总数:x+y(fast指针在slow指针入环的第一圈就能和slow指针相遇);
fast指针走的节点总数:x+y+n(y+z),其中n表示fast指针在环内走的圈数;
由于slow指针和fast指针是同时出发,而fast指针的速度是slow指针的两倍,那么当他们相遇时, 2(x+y)=x+y+n(y+z) => x=(n-1)(y+z)+z;
当n=1时,也就是在fast走过一圈后与slow相遇,上述公示为 x=z。
也就是说,定义一个指针index1从相遇点出发,定义一个指针index2从head点出发,当两个指针同时以同样的速度前进,他们会在入环节点相遇。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
//fast指针先走,每次走两步
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
//slow指针走,每次走一步
slow = slow->next;
//判断两个指针有没有相遇,如果相遇,表示有环;否则,表示无环
if(fast == slow){
//相遇后,要找到入环点
ListNode* index1 = fast;
ListNode* index2 = head;
//两个指针在入环点相遇
while(index1!= index2){
index1 = index1->next;
index2 = index2->next;
}
return index1;
}
}
return NULL;
}
};
图源:代码随想录