24.两两交换链表中的节点
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(0);//设置虚拟节点
dummyHead->next = head;
ListNode* cur = dummyHead;
while(cur->next != nullptr && cur->next->next != nullptr)
{
ListNode* temp1 = cur->next;//提前储存结点的值
ListNode* temp2 = cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = temp1;
temp1->next = temp2;
cur = cur->next->next;
}
return dummyHead->next;
}
};
这道题目的重点就是要设置结点提前储存cur->next和cur->next->next->next的值,这样做的目的是为了防止转变结点方向之后,某些结点的前后位置发生改变造成内容丢失。
19.删除链表的倒数第N个节点
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* fast = dummyHead;
ListNode* slow = dummyHead;
while(n-- && fast != NULL)
{
fast = fast->next;
}
fast = fast->next;
while(fast != NULL)
{
slow = slow->next;
fast = fast->next;
}
slow->next = slow->next->next;
return dummyHead->next;
}
};
这道题使用的是快慢指针的思想,先让快指针提前走n+1步,这样慢指针和快指针同时出发,快指针走到链表末端时,慢指针正好走到要删除的结点的前一个结点,之后执行 slow->next = slow->next->next;操作,就能把倒数第n个结点删除了。这题同样也设置了虚拟节点。
07. 链表相交
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0,lenB = 0;
while(curA != NULL)
{
lenA++;
curA = curA->next;
}
while(curB != NULL)
{
lenB++;
curB = curB->next;
}
curA = headA;
curB = headB;
int n = lenA > lenB? lenA-lenB:lenB-lenA;
if(lenA > lenB){
while(n--)
{
curA = curA->next;
}
}
if(lenB > lenA)
{
while(n--)
{
curB = curB->next;
}
}
while(curA != NULL)
{
if(curA == curB)
{
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
这题的最重要的思想就是要事先把A,B两个链表对齐:先计算下两个链表的长度并对比,计算出A,B链表的差值,将指向长链表的指针移动n位,让其与短链表对齐,之后长短链表指针同时后移,直到遇见curA==curB,这就是链表相交的点,返回该结点的值;如若没有相等的值,则两链表不相交,返回NULL。
142.环形链表II
这道题本菜鸟觉得是有点难度的,是看了解析之后才开始的做题,代码如下:
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)//判断是否有环,fast与slow相遇则表示有环存在
{
ListNode* curA = head;
ListNode* curB = fast;
while(curA != curB)
{
curA = curA->next;
curB = curB->next;
}
return curA; //curA,curB相遇时,则是环形入口
}
}
return NULL;
}
};
指定一个fast和slow指针,fast一次走两步,slow每次走一步。如果有环,slow指针和fast指针必会在环形内相遇,如果没有相遇,则判定没有环。
slow和fast的点如上图所示,slow指针经过的路径为(x+y),fast经过的路径为x+y+n(y+z),n为fast经过了多少次环。又因为2*slow指针经过的路径=fast指针经过的路径,所以2*(x+y)=x+y+n(y+z),可得x = n (y + z) - y,提出来一个(y+z),可得x = (n - 1) (y + z) + z 。当n=1时,得x=z。
这样分析之后,我们可以设置两个指针,一个从head结点出发,一个从fast指针与slow指针相遇的节点出发,两指针相遇的时候,就是环的入口。
今天的四道题目也结束了,希望自己常看常新,时常回顾。