目录
第一题:面试题02.02.返回倒数第K个节点 OJ链接
题目
思路
我们可以使用快慢指针法来解决这个问题。具体思路是:
定义两个指针 fast 和 slow,初始时都指向链表的头节点 head。
先让 fast 指针向前移动 k 步。
然后让 fast 和 slow 指针同时向前移动,直到 fast 指针指向链表的末尾(即 fast == NULL)。此时,slow 指针所指向的节点就是倒数第 k 个节点。
图解

具体代码解答
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//利用快慢指针,快指针比慢指针先走K
//当快指针走到NULL时,慢指针刚好为倒数第 k 个节点
int kthToLast(struct ListNode* head, int k)
{
struct ListNode* fast=head;
struct ListNode* slow=head;
int i=0;
for(i=0;i<k;i++)
{
fast=fast->next;
}
while(fast!=NULL)
{
fast=fast->next;
slow=slow->next;
}
return slow->val;
}
第二题:160.相交链表 OJ链接
题目
思路
1.找出长链表与短链表相差的部分
2.让长指针先走相差步
3.同时走至到相交
图解
链表A的指针 curA 和链表B的指针 curB 分别遍历各自链表后,通过计算得到长度差 gap 。

对于链表A(短链表, shortList 指向其起始段)和链表B(长链表, longlist 指向其起始段),先让长链表的指针移动 gap 步(图中体现为 longlist 从 b1 移动到 b2 ),使两个链表的剩余长度一致。
之后两个指针( shortList 和 longlist )同步移动,最终会在相交节点 c1 处相遇,以此找到两个链表的相交节点。

具体代码解答
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//思路:1.找出长链表与短链表相差的部分
//2.让长指针先走相差步
//3.同时走至到相交
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode* curA=headA;
struct ListNode* curB=headB;
int lenA=1;
int lenB=1;
while(curA->next)
{
curA=curA->next;
lenA++;
}
while(curB->next)
{
curB=curB->next;
lenB++;
}
int gap=abs(lenA-lenB);
struct ListNode* longList=headA;
struct ListNode* shortList=headB;
if(lenA<lenB)
{
longList=headB;
shortList=headA;
}
while(gap--)
{
longList=longList->next;
}
while(shortList!=longList)
{
longList=longList->next;
shortList=shortList->next;
}
return shortList;
}
第三题:203.移除链表元素 OJ链接
题目

思路
1.创建一个新链表
2.如果原链表中Node.val!=val,则把其尾插到新链表中。
图解
if(pcur->val == val):判断当前 pcur 指向的节点值是否等于要删除的值(假设此处要删除的是 6)。
pcur = pcur->next:因为该节点值等于 val,所以不将其插入新链表,直接让 pcur 后移,处理原链表的下一个节点(值为 3 的节点)。
具体代码解答
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
//创建一个空链表
ListNode* newHead,*newTail;
newHead = newTail = NULL;
//遍历原链表
ListNode* pcur = head;
while(pcur)
{
//找值不为val的节点,尾插到新链表中
if(pcur->val != val)
{
//链表为空
if(newHead == NULL)
{
newHead = newTail = pcur;
}else{
//链表不为空
newTail->next = pcur;
newTail = newTail->next;
}
}
pcur = pcur->next;
}
if(newTail)
newTail->next = NULL;
return newHead;
}
题目
第四题:206.反转链表 OJ链接
题目

思路
这道题博主将介绍两种解法
解法一:创建一个新链表,将原链表的节点拿过来依次头插
解法二:创建三个指针,完成原链表的翻转
图解(解法一)
展示原链表和新链表的初始指针状态:
原链表:节点依次为 1→2→3→4→5,pcur 指向原链表的头节点(值为 1),next 暂存 pcur 的下一个节点(值为 2)。
新链表:newHead 初始为 NULL(新链表还没有节点)。

执行 pcur->next = newHead:原链表中值为 1 的节点(pcur 指向的节点)的 next,从 “指向值为 2 的节点” 变为 “指向 newHead(即 NULL)”。
执行 newHead = pcur:新链表的头节点更新为值为 1 的节点(此时新链表为 1→NULL)。
右侧的 “相当于” 图示,是对 “头插后新链表形态” 的简化呈现,帮助直观理解 “新链表的头变为 1,且 1 的 next 是 NULL”。

newHead 指向值为 1 的节点(新链表的头)。
pcur 此时还未移动(代码中下一步才会执行 pcur = next),所以仍然指向值为 1 的节点(但后续会移动到 next 暂存的 “值为 2 的节点”)。

执行 pcur = next(next 是第一步暂存的 “值为 2 的节点”),所以 pcur 现在指向值为 2 的节点。
原链表剩下的节点为 2→3→4→5,后续会重复 “头插 2、3… 直到原链表遍历完” 的步骤。
图解(解法二)
初始状态
原链表:节点依次为 1→2→3→4→5,是待反转的链表。
指针指向:
n2 指向原链表的头节点(值为 1 的节点);
n3 指向原链表中 n2 的下一个节点(值为 2 的节点);
n1 指向 NULL(代表 “已完成反转的部分”,初始时还没有反转节点,所以为 NULL)。

第一次反转操作后
这一步对应代码中 n2->next = n1; n1 = n2; 的逻辑:
n2->next = n1:将当前 n2 指向的节点(值为 1 的节点)的 next 指向 n1(此时 n1 是 NULL),相当于把 “值为 1 的节点” 从原链表断开,并作为已反转部分的第一个节点(尾节点,因为 next 是 NULL)。
n1 = n2:更新 “已反转部分的尾指针”n1,使其指向刚完成反转的节点(值为 1 的节点)。

n2 = n3:n2 移动到值为 2 的节点,为下一轮反转做准备。
若 n3 非空则执行 n3 = n3->next;” 的逻辑

具体代码解答(解法一)
解法一:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* newHead=NULL;
struct ListNode* pcur=head;
while(pcur)
{
struct ListNode* next=pcur->next;
pcur->next=newHead;
newHead=pcur;
pcur=next;
}
return newHead;
}
具体代码解答(解法二)
解法二:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* n1=NULL;
struct ListNode* n2=head;
//判空
if(head==NULL)
{
return NULL;
}
struct ListNode* n3=head->next;
while(n2)
{
n2->next=n1;
n1=n2;
n2=n3;
if(n3)
{
n3=n3->next;
}
}
return n1;
}




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



