[力扣c语言实现] 链表(19+142)

链表

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
解释:链表中没有环。

提示:

扫描二维码关注公众号,回复: 13128558 查看本文章

链表中节点的数目范围在范围 [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;
}

f)//先判断,因为有可能两者的入环点为第一个节点,如{1,2}链表,1为入环处
{
break;
}

    ps = ps->next;
    pf = pf->next;
}

return pf;

}

猜你喜欢

转载自blog.csdn.net/dengwodaer/article/details/114875322
今日推荐