链表相关面试题第三篇

16 篇文章 14 订阅

在这里插入图片描述

系列文章目录




前言


在这里插入图片描述

一、环形链表

环形链表

1.题目描述

  1. 给定一个链表,判断链表中是否有环。
  2. 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
  3. 注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。如果链表中存在环,则返回 true 。 否则,返回 false 。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2.解题思路

在这里插入图片描述
代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head)
{
    struct ListNode* fast=head,*slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            return true;
        }
    }
    return false;
}

二、环形链表进阶

环形链表进阶

1.题目描述

  1. 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
    为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
  2. 说明:不允许修改给定的链表。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2.解题思路

在这里插入图片描述
代码如下:

struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode* fast=head,*slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(slow==fast)
        {
            struct ListNode* meet=fast;
            while(meet!=head)
            {
                meet=meet->next;
                head=head->next;
            }
            return meet;
        }
    }
    return NULL;
}

三、复杂带随机指针的链表

复杂带随机指针的链表

1.题目描述

  1. 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
  2. 例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。
  3. 返回复制链表的头节点。
  4. 用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
  5. val:一个表示 Node.val 的整数。random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。你的代码只接受原链表的头节点 head 作为传入参数。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2.解题思路

在这里插入图片描述
代码如下:

struct Node* copyRandomList(struct Node* head) 
{
    if(head==NULL)
    {
        return NULL;
    }
    //1.拷贝节点挂在原节点的后面
	struct Node* cur=head;
    while(cur)
    {
        struct Node* next=cur->next;
        struct Node* copy=(struct Node*)malloc(sizeof(struct Node));
        copy->val=cur->val;
        cur->next=copy;
        copy->next=next;
        cur=next;
    }
    //2.处理copy节点的random
    cur=head;
    while(cur)
    {
        struct Node* copy=cur->next;
        if(cur->random==NULL)
        {
            copy->random=NULL;
        }
        else
        {
            copy->random=cur->random->next;
        }
        cur=copy->next;
    }
    //3.把拷贝的节点取下来链接到一起,恢复原链表
    cur=head;
    struct Node* copyHead,*copyTail;
    copyHead=copyTail=(struct Node*)malloc(sizeof(struct Node));
    while(cur)
    {
        struct Node* copy=cur->next;
        struct Node* next=copy->next;
        //尾插
        copyTail->next=copy;
        copyTail=copyTail->next;

        cur->next=next;
        cur=next;
    }
    struct Node* guard=copyHead;
    copyHead=copyHead->next;
    free(guard);
    return copyHead;
}

四、对链表进行插入排序

对链表进行插入排序

1.题目描述

在这里插入图片描述

  1. 对链表进行插入排序。
    插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
    每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。
  2. 插入排序算法:
    插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
    每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
    重复直到所有输入数据插入完为止。

2.解题思路

在这里插入图片描述
代码如下:

struct ListNode* insertionSortList(struct ListNode* head)
{
    if(head==NULL||head->next==NULL)
    {
        return head;
    }
    //起始条件
    struct ListNode* sortHead=head;
    struct ListNode* cur=sortHead->next;
    sortHead->next=NULL;
    while(cur)  //终止条件cur为空
    {
        struct ListNode* next=cur->next;
        struct ListNode* p=NULL;
        struct ListNode* c=sortHead;
        while(c)
        {
            if(c->val>cur->val)
            {
                break;
            }
            else
            {
                p=c;
                c=c->next;
            }
        }
        if(p==NULL)  //一个节点都没有
        {
            cur->next=c;
            sortHead=cur; //cur来当头节点
        }
        else        //中间插入
        {
            p->next=cur;
            cur->next=c;
        }
        cur=next;
    }
    return sortHead;
}

五、删除链表中重复节点,重复节点不保留

删除链表中重复节点,重复节点不保留

1.题目描述

  1. 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
    在这里插入图片描述

2.解题思路

在这里插入图片描述
代码如下:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) 
    {
        if(pHead==NULL||pHead->next==NULL)
        {
            return pHead;
        }
        struct ListNode* prev=NULL;
        struct ListNode* cur=pHead;
        struct ListNode* next=pHead->next;
        while(next)
        {
           if(cur->val==next->val)
           {   
              while(next && cur->val==next->val)
              {
                 next=next->next;
              }
              while(cur!=next)
              {
                  struct ListNode* del=cur;
                  cur=cur->next;
                  free(del);
              }
              if(prev==NULL)
              {
                  pHead=cur;
              }
              else
              {
                  prev->next=cur;
              }
              if(next)
              {
                  next=next->next;
              }
           }
           else
           {
            prev=cur;
            cur=next;
            next=next->next;
           }
        }
        return pHead;
    }
};

总结

以上就是今天要讲的内容,本文仅仅简单介绍了链表几道经典题的解法,会继续发布链表后面的题目解法,希望大家多多支持。还有,如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。
在这里插入图片描述

  • 33
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 33
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

森明帮大于黑虎帮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值