链表
19.删除链表的倒数第N个节点
使用快慢指针,快指针先走N步,然后快慢指针一起前进,直到快指针指向NULL,此时慢指针指向的就是要删除的节点,删除即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//快慢指针
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
typedef struct ListNode Node;
Node *pPre = head;
Node *pNext = head;
Node *ptmp = head;
int cnt = n;
if (head== NULL || head->next == NULL)
{
return NULL;
}
while (cnt)
{
pNext = pNext->next;
cnt -=1;
}
if (pNext == NULL)
{
return head->next;
}
while (pNext)
{
ptmp = pPre;
pPre = pPre->next;
pNext = pNext->next;
}
ptmp->next = ptmp->next->next;
return head;
}
142. 环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
进阶:
你是否可以使用 O(1) 空间解决此题?
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
提示:
链表中节点的数目范围在范围 [0, 104] 内
-105 <= Node.val <= 105
pos 的值为 -1 或者链表中的一个有效索引
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
本题分析如下:
如上图所以,有一条环形链表,如何找到它的入环结点2?
以下分析过程来自力扣大佬:假设从链表头到入环节点的距离为a,从入环节点到pfast和pslow的相遇点为b,从相遇点到入环点的距离为c(图中的相遇点为4处,这个相遇点只针对此条环形链表,由我本人手动推算而来)。
那么,慢指针每次走一步,快指针每次走两步,当快慢指针相遇之时,假设慢指针的移动距离为x,所以快指针的行走距离为2x,于是就有,x = a+b,2x = a+b+c+b,由此,推断出 a=c,于是,此时我们让相遇点出的慢指针回到链表开头,此时两人一起前进,一定会在入环处相遇(因为a==c)
详细实现:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
typedef struct ListNode Node;
if (head == NULL || head->next == NULL)
{
return NULL;
}
Node *pf = head;
Node *ps = head;
int flag = 0;
while (ps)//先判断链表是否有环,没有的话直接返回空
{
ps = ps->next;
if (pf->next&&pf->next->next)
{
pf = pf->next->next;
}
else
{
flag = 0;
break;
}
if (ps == pf)
{
flag = 1;
break;
}
}
if (flag == 0)//链表无环,直接返回
{
return NULL;
}
ps = head;//慢指针回头起点,
printf("%d\n",pf->val);
while (ps)//快慢指针同时前进相同的距离,根据推算的理论,他们在前进某一个相同的距离s(s>=0)后就会相遇
{
if (ps == pf)//先判断,因为有可能两者的入环点为第一个节点,如{1,2}链表,1为入环处
{
break;
}
ps = ps->next;
pf = pf->next;
}
return pf;
}