链表经典练习题

本文介绍了如何通过三指针法、双指针法等技巧解决单链表相关问题,包括反转链表、查找中间结点、合并有序链表、分割链表、约瑟夫问题、判断环和复制随机链表。这些题目旨在巩固链表基础知识和提高编程能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

前言:

一、反转单链表

二、链表的中间结点

三、合并两个有序链表

四、分割链表

五、约瑟夫问题

六、判断链表是否有环?

七、求环形链表的入口点

 八、输入一个链表,输出该链表中倒数第k个结点

九、输入两个链表,找出它们的第一个公共结点

十、随机链表的复制

最后:


前言:

        大家经过前面的学习,已经对链表有了初步的了解,那么,我为大家准备了几道题目,大家一起来练习巩固一下吧!

一、反转单链表

        给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

      

 先来一道简单题来练练手,题目的要求为反转链表,相信会有部分同学会说,像数组一样,从后往前遍历不就行了,对此我只能说,很抱歉,这个是单链表,不是双链表(以后做题无说明均为单链表),那既然是单链表,我们又该如何破局呢?大家可自行思考一下方法。

        本题提供的方法为三指针法(方法不唯一,以下题均如此),即运用三指针进行求解。以下为思路:

        代码如下:

typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) {
    if(head == NULL)
    {
        return head;
    }
    ListNode* p1,*p2,*p3;
    p1 = NULL,p2 = head,p3 = p2->next;
    while(p2)
    {
        p2->next = p1;
        p1 = p2;
        p2 = p3;
        if(p3)
        p3 = p3->next;
    }
    return p1;
}

         题目链接:. - 力扣(LeetCode)

        大家可自行前去练习。

二、链表的中间结点

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

         本题方法为:双指针法。

        具体实现思路为:使用快慢指针,一个比另外一个快一步即可。以下是一个例子帮助大家理解:很直观的例子就是五十步笑百步:假设路一共100米,慢逃兵走一步,快逃兵走两步,那么当快逃兵走到终点时,慢逃兵刚好就停在中间,然后开始五十步笑百步。

        代码实现如下:

typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
    ListNode* fast = head;
    ListNode* slow = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

         题目链接:. - 力扣(LeetCode)

三、合并两个有序链表

        将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

        此题要求为对其合并并排序,相信有人会有这样想法:先插入在排序,其实这个方法说可以也可以,就是有点麻烦,因为这是链表不是数组,修改链表的指向,是比较麻烦的一件事。所以,我们采取以下的方法:创建一个新链表,并设立哨兵位。然后逐渐插入,把这两个链表元素值最小的进行插入,这样即可满足题目要求。 

        代码实现:

typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    //如果List1和list2中有一个为空就直接返回另一个链表
    if(list1 == NULL)
    {
        return list2;
    }
    if(list2 == NULL)
    {
        return list1;
    }
    //定义l1,l2指针分别指向list1和list2的头节点
    ListNode* l1, *l2;
    ListNode* newhead, *newtail;
    //给新链表的开辟一个哨兵位
    newhead = newtail = (ListNode*)malloc(sizeof(ListNode));
    l1 =
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值