24. 两两交换链表中的节点
自己看随想录的时候感觉很简单,但是实敲的时候有好多小地方翻不清楚,所以还是看了视频。接下来是我第一次打困惑的地方,也是值得注意的地方:1、首先是便利条件,这样做是为了确保cur节点后面有两个非空节点,这样才有进行下次循环的必要;2、第二点是,cur要指向本次需要翻转的两个节点的前一个节点。并且设置两个tmp指针:

当cur指向2时就丢掉的1的地址,所以要用tmp指向1;当2指向1时就丢掉了3的地址,所以要用tmp2指向3;
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
//设置虚拟头结点
ListNode* dummyhead = new ListNode(0, head);
ListNode* cur = dummyhead;
while(cur->next!=NULL&&cur->next->next!=NULL)
{
ListNode* tmp = cur->next;
ListNode* tmp1 = cur->next->next->next;
cur->next = tmp->next;
cur->next->next=tmp;
tmp->next=tmp1;
cur = cur->next->next;
}
ListNode* result = dummyhead->next;
delete dummyhead;
return result;
}
};
19.删除链表的倒数第N个节点
这次依然是直接看文章,该题采用双指针的解法,快指针先移动,和慢指针之间差n个节点,然后快慢同时移动最后,这样快指针移动到空节点的时候,慢指针就指向倒数第n个节点的前一个节点,方便删除。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
//设置虚拟头节点
ListNode* dummyhead = new ListNode(0, head);
ListNode* fast = dummyhead;
ListNode* slow = dummyhead;
while(n-- && fast != NULL) {
fast = fast->next;
}
fast = fast->next;
while(fast!=nullptr)
{
fast = fast->next;
slow = slow->next;
}
ListNode* tmp = slow->next;
slow->next=slow->next->next;
delete tmp;
tmp = NULL;
return dummyhead->next;
}
};
面试题 02.07. 链表相交
这个题是找两个链表开始相交的地方。关键点是找到哪个链表更长,然后移动长链表的头节点,使其移动到和短链表头节点对其的地方,如图所示:

然后同时移动,直到找到curA和curB相同的时候。
/**
* 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* 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;
if(lenB>lenA)
{
swap(lenA, lenB);
swap(curA, curB);
}
int cha = lenA-lenB;
while(cha--)
{
curA=curA->next;
}
while(curA!=NULL)
{
if(curA==curB) return curA;
curA=curA->next;
curB=curB->next;
}
return NULL;
}
};
142.环形链表II
这里卡哥讲了一个非常便于理解快慢指针相遇的逻辑:快指针每次移动两个节点,慢指针每次移动一个节点,快指针相当于以一个节点的速度去追慢指针!所以一定会相遇。
这个题要找环的入口,主要有两个计算,第一是计算快指针和慢指针会不会相遇;第二是计算唤醒入口的节点在哪里。前面已经讲了如何判断是否有环,接下来解决第二个问题:
如果有环,两个节点在图中相遇,此时:
fast走过的路程是:x+y+n(z+y) n大于等于1;
slow走过的路程是:x+y
这里卡哥解释了为什么slow在环内不到一圈就能被追上。
由于fast走过的路程一定是slow的2倍,所以:x+y+n(z+y)=2(x+y)
因此:x=nz+(n-1)y=z+(n-1)(z+y) n大于等于1
这个式子的意思是一个指针从相遇点出发,一个指针从头节点出发,一定会在入口处相遇。
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(fast==slow)
{
ListNode* index1 = head;
ListNode* index2 = fast;
while(index1!=index2)
{
index1 = index1->next;
index2 = index2->next;
}
return index1;
}
}
return NULL;
}
};

463

被折叠的 条评论
为什么被折叠?



