单链表OJ题

目录

一 . 关于 有环问题

二. 返回 进环的 第一个节点

三.随机链表的复制


一 . 关于 有环问题

141. 环形链表 - 力扣(LeetCode)

如果 没环 最后肯定到 NULL 指针,有环 就会 死循环 无法找到  NULL 。

这题可以用快慢指针 来解决 也就是说他们 迟早会相遇 (为什么一定会相遇?可以推导出来)。

所以这题就是 追及 以及 相遇 的问题。

设他们相差 N 步,如果fast走 两 步,slow 走一步。

 fast 每次 追一步 ,肯定可以追到。

如果 slow走1步 ,fast 走 3  步4 步 5 步..... 他们会相遇吗?  答案是会的!!!

我们用走三步来举例 ,也就是 fast 每次 追两步,设他们依然相差N步,那么就会有这样的表格:

 当N为奇数时,每次追两步,他们就 追过头 了。

那我们继续设 圈大小为c   又要追c-1 步,c-1 如果是偶数,那么每次追两步就可以追上;

如果c-1是奇数,每次追两步,依旧会重复这个过程吗?

也就是存在结论: N 为奇数,C为偶数 那就一定追不上。(其实这个结论是不存在的)

4

偶数 !=  偶数 - 奇数 , 所以之前结论不成立。

总结:也就是无论fast走2步以上,他们都会相遇!!!

我自己的题目的答案

typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) {
    if(head == NULL || head->next == NULL)
        return false;
    ListNode* slow = head;
    ListNode* fast = head->next->next;
    while(fast && fast->next)
    {
        if(fast == slow)
        {
            return true;
        }
        slow = slow->next;
        fast = fast->next->next;
    }
    return false;
}

二. 返回 进环的 第一个节点

142. 环形链表 II - 力扣(LeetCode)

上题已经说明  无论fast走 多少步都会相遇。

这题其实也是推导公式,把他们相遇的点设为meet  从头开始数L就可以找到进环的节点

也就是说 L = C - N 因此只要 meet和头节点 同时一起走 就可以找到进环节点!!!

我的答案

typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head)
{
    if(head == NULL || head->next == NULL)
    {
        return NULL;
    }
    ListNode* slow = head;
    ListNode* fast = head;
    ListNode* meet = NULL;
    while(fast && fast->next)
    {        
        slow = slow->next;
        fast = fast->next->next;
        if(fast == slow)
        {
            meet = slow;
            break;
        }
    }
    if(meet != NULL)//有meet才可以继续走噢
    {
        while(head != meet)
        {
           meet = meet->next;
           head = head->next;
        }
        return meet;           
    }
    else
        return NULL;
}

三.随机链表的复制

138. 随机链表的复制 - 力扣(LeetCode)

他的意思就是重新复制一个一模一样的新链表

如何做呢?其实有一种办法,先在它 中间遍历建立一个节点遍历random节点遍历切断节点

第一步:遍历 建立新节点

第二步:遍历 把random链接

        if(cur->random==NULL)
        {
            copy->random=NULL;  //比如cur->random 为空


        }
        else
       {
            copy->random = cur->random->next;  //如图所示

             
       }

第三步: 遍历把 节点分开,再链接新节点

最后返回 head->next。

typedef struct Node Node;
struct Node* copyRandomList(struct Node* head) {
        if(head==NULL)
        return NULL;
	Node* cur = head;
    Node* copy = NULL;
//第一步 遍历中间节点
     while(cur)
     {
         Node* copy = (Node*)malloc(sizeof(Node));
         copy->val = cur->val;
         copy->next = cur->next;
         cur->next = copy;
         cur = copy->next;
    }
//第二步 遍历建立random节点(最困难)
    cur = head;
     while(cur)
      {
          copy = cur->next;
          if(cur->random == NULL)
          {
              copy->random = NULL;
          }
         else{
              copy->random = cur->random->next;
         }
          cur = copy->next;
       }
//第三步 遍历把 新节点连接,断除旧节点,考验基础内容
    cur = head;
    while(cur)
    {
        copy = cur->next;
        cur = copy->next;
        if(cur)
        copy->next = cur->next;
    }
    return head->next;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值