一、24 两两交换链表中的节点
//迭代版本
struct ListNode* swapPairs(struct ListNode* head) {
//定义虚拟头节点
struct ListNode* dummyhead = (struct ListNode*)malloc(sizeof(struct ListNode));
dummyhead->next = head;
struct ListNode* cur = dummyhead;
while(cur->next!=NULL&&cur->next->next!=NULL)
{
struct ListNode*tmp = cur->next;//保存节点1
struct ListNode*p=cur->next->next->next;//保存节点3
cur->next = cur->next->next;//cur->节点2
cur->next->next = tmp;//节点2->节点1
tmp->next=p;//节点1->节点3//完成第一次交换
cur=cur->next->next;//cur走到节点1的位置
}
return dummyhead->next;
}
//递归版本
struct ListNode* swapPairs(struct ListNode* head) {
//结束调价:头节点为空或头结点的下一个为空
if(head == NULL||head->next == NULL)
return head;
//创建一个节点指针类型保存头结点下一个节点
struct ListNode*cur = head->next;
//更改头结点+2位节点后的值,并将头结点的next指针指向这个更改过的list
head->next = swapPairs(cur->next);
//将新的头结点的next指针指向老的头节点
cur->next = head;
return cur;
}
在这里,小编还是建议大家先弄明白迭代版本,然后再理解递归版本!!!
二、19 删除链表的倒数第n个节点
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode*dummyhead = (struct ListNode*)malloc(sizeof(struct ListNode));
dummyhead->next = head;//创建了一个虚拟头节点
struct ListNode*fast = dummyhead->next;//让快指针多走一步,慢指针就会停在n的前驱那里
struct ListNode*slow = dummyhead;
while(n--&&fast!=NULL)
{
fast = fast->next;
}
while(fast!=NULL)
{
fast = fast->next;
slow = slow->next;
}
slow->next=slow->next->next;//删除操作
return dummyhead->next;
}
在这道题里,大家一定要注意的是如何找到倒数第n个节点!要理解这种方法。
三、 面试题02.07 链表相交
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *curA = headA;
struct ListNode *curB = headB;
int lenA = 0,lenB = 0;//链表A和B的长度
for(curA = headA;curA!=NULL;curA=curA->next)
lenA++;
for(curB = headB;curB!=NULL;curB=curB->next)
lenA++;
//长度差
int tmp;
//计算长度差,让curA和lenA成为长链表的指针和长度
if(lenA>lenB)
{
curA=headA;
tmp = lenA-lenB;
}
else
{
curA = headB;
tmp = lenB-lenA;
}
//对齐指针
while(tmp--&&curA!=NULL)
curA =curA->next;
//找交点
while(curA!=NULL)
{
if(curA==curB)//找到交点就return
return curA;
//没有找到继续向后移动
curA = curA->next;
curB= curB->next;
}
return NULL;//没有找到返回NULL;
}
这道题的思路是先定义两个指针指向两个链表的头节点,然后定义两个链表的长度,计算链表的长度以及长度差,将长链表的头节点和长度够设置为curA和lenA,然后将两个链表的指针对齐,这时就开始遍历进行比较了。当找到交点时,return curA;若没找到两个指针继续向后移动;若遍历结束还没找到,则return NULL。
四、142 环形链表||
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode *fast = head;
struct ListNode *slow = head;
while(fast!=NULL&&fast->next!=NULL){
fast = fast->next->next;
slow=slow->next;
//判断环
if(fast == slow){
//找环的入口
struct ListNode *p = fast;
struct ListNode *q = head;
while(p!= q){
p = p->next;
q=q->next;
}
return p;//找到入口
}
}
//不是环
return NULL;
}
对于环形链表这道题来说,重点在于判断环和找到环的入口。
首先是判断环,定义两个指针分别为快指针和慢指针,快指针一次走两步,慢指针一次走一步,如果快慢指针相遇则链表有环。这里有朋友可能会担心快指针为什么不会跳过慢指针,因为快指针走两步,慢指针走一步相当于快指针比慢指针多走一步,这样就不会跳过慢指针。
接下来就是在判断有换的基础上找到环的入口。这里为了帮助大家理解,我准备了一个图片,大家可以学习图片自行模拟!
在搞清楚环这个等式之后,有的朋友可能会想,为什么快慢指针不能在第一圈就相遇呢?
还是用图来解决,这里的图使我们把换展开之后的样子,没有上图的x部分,大家不要弄混了!
好啦,这就是今天博客的全部内容,感谢大家的观看啦!!!