4道题目
24. 两两交换链表中的节点
19. 删除链表的倒数第 N 个结点
面试题 02.07. 链表相交
142. 环形链表 II
解题理解
24
也是比较典型的特殊头指针处理的情况,所以创建一个虚拟结点指向头节点。不过这里需要改变一对结点的next方向,所以在遍历过程中需要两个临时结点。反转过程比较绕,代码如下。
ListNode* tmp = cur->next;
ListNode* tmp1 = cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = tmp;
cur->next->next->next = tmp1;
cur = cur->next->next;
这里可以看出,每次在出现断链情况时,都会用临时结点重新接上,所以只要搞清楚哪里需要断链才能反转指针,就可以把反转过程理清楚。
19
删除链表第n个结点比较简单,倒数第N个可能不一样,但其实一模一样。删除操作是通用的,重点是如何找到倒数第N个结点,倒数第N个是相对于结尾说的,可以利用双指针法,让快指针比慢指针提前前进N步,这样当快指针的下一个结点为空时,慢指针正好指向待删除结点的前一个(指向前一个结点比较容易删除目标结点),这道题依然采用虚拟结点指向头节点的方法。
链表相交
这道题跟上一道题很像,只要反着看就会有思路。题目说要找到两个链表的交点,即公共子链表的起始点,正着看不太好找,反着看容易看出需要找的是倒数第N个结点。这里倒数第N个结点对于两个链表都是各自的倒数第N个,但两个链表长度可能不一样,所以遍历过程中一定存在有提前出发的指针,因此采用快慢指针法。
先统计两条链表长度,计算出差值S,然后让快指针先从更长的链表出发,走过S步后,让慢指针从更短的链表出发,两指针同时移动,当相等的时候就找到了公共链表的起始点。
环形链表 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(fast == slow){
ListNode* p = fast;
ListNode* q = head;
while(p != q){
p = p->next;
q = q->next;
}
return q;
}
}
return NULL;
}
};