链表面试题

news2024/10/7 16:23:20

链表面试题

  • 1. 删除链表中等于给定值 val 的所有结点。
  • 2. 反转一个单链表。
  • 3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
  • 4. 输入一个链表,输出该链表中倒数第k个结点。
  • 5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有结点组成的。
  • 6. 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 。
  • 7. 链表的回文结构。
  • 8. 输入两个链表,找出它们的第一个公共结点。

1. 删除链表中等于给定值 val 的所有结点。

题目链接
在这里插入图片描述
解题思想:用两个指针,来遍历整个链表,当出现cur指向的结点和val的值相等就,就将pre指向的结点指向cur的下一个结点,在free掉cur的结点。需要注意的特殊情况是,头删和空链表的情况。

struct ListNode* removeElements(struct ListNode* head, int val){
    if(head==NULL)
        return NULL;
    struct ListNode*pre;
    struct ListNode*cur;
    pre=head;
    cur=head;
    while(cur)
    {
        if(cur->val==val)
        {
            if(cur==head)
            {
                head=head->next;
                free(cur);
                cur=head;
            }
            else
            {
                pre->next=cur->next;
                free(cur);
                cur=pre->next;
            }
        }
        else
        {
            pre=cur;
        cur=cur->next;
        }
    }
    return head;
}

2. 反转一个单链表。

题目链接
解法一:用三指针来逆向指向结点

struct ListNode* reverseList(struct ListNode* head){
    if(head==NULL)
    {
        return head;
    }
    struct ListNode*n1,*n2,*n3;
    n1=NULL;
    n2=head;
    n3=n2->next;
    while(n2)
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)
        {
            n3=n3->next;
        }
    }
    return n1;
}

解法二:头插法插入结点

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode*new_head;
    new_head=(struct ListNode*)malloc(sizeof(struct ListNode));
    if(new_head==NULL)
    {
        exit(1);
    }
    new_head->next=NULL;
    struct ListNode*p=head;
    while(p)
    {
        struct ListNode*tmp=p->next;
        p->next=new_head->next;
        new_head->next=p;
        p=tmp;
    }
    head=new_head->next;
    free(new_head);
    return head;
}

3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

题目链接
解题思想:用快慢指针,慢指针一次走一步,快指针一次走两步,当快指针走完整个链表的时候,慢指针刚好走完链表的一半。此时慢指针就是中间结点。
注意:要考虑奇数和偶数的问题!
在这里插入图片描述

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

4. 输入一个链表,输出该链表中倒数第k个结点。

题目链接
解题思路:用快慢指针来解决,先让快指针先走k步,在让慢指针开始走,当快指针走完的时候,慢指针的位置就是倒数第K个结点。
注意:①判断链表是否为空;②倒数第k个数是否存在

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    // write code here
    if(pListHead==NULL||k<1)
    {
        return NULL;
    }
    struct ListNode*low,*fast;
    low=fast=pListHead;
    for(int i=0;i<k;i++)
    {
        if(fast==NULL)
        {
            return NULL;
        }
        fast=fast->next;
    }
    while(fast)
    {
        low=low->next;
        fast=fast->next;
    }
    return low;
}

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

题目链接
解题思路:两个链表比较,小的尾插到新的结点里。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    struct ListNode*head=(struct ListNode*)malloc(sizeof(struct ListNode));
    if(head==NULL)
    {
        exit(1);
    }
    head->next=NULL;
    struct ListNode*cur1,*cur2,*tail;
    tail=head;
    cur1=list1;
    cur2=list2;
    while(cur1&&cur2)
    {
        if(cur1->val<cur2->val)
        {
            tail->next=cur1;
            tail=cur1;
            cur1=cur1->next;
        }
        else
        {
            tail->next=cur2;
            tail=cur2;
            cur2=cur2->next;
        }
    }
    if(cur1)
    {
        tail->next=cur1;
    }
    if(cur2)
    {
        tail->next=cur2;
    }
    struct ListNode*tmp=head->next;
    free(head);
    return tmp;
}

6. 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 。

题目链接
解题思路:创建两个链表,一个尾插小于x结点,一个尾插大于等于x的结点,最后将两个链表合并。

ListNode* partition(ListNode* pHead, int x) {
        // write code here
        struct ListNode*GreaterHead,*LowerHead,*GreaterTail,*LowerTail;
        GreaterHead=GreaterTail=(struct ListNode*)malloc(sizeof(struct ListNode));
        LowerTail=LowerHead=(struct ListNode*)malloc(sizeof(struct ListNode));
        if(GreaterHead==NULL&&LowerTail==NULL)
        {
            exit(1);
        }
        GreaterHead->next=LowerHead->next=NULL;
        struct ListNode*cur=pHead;
        while(cur)
        {
            if(cur->val<x)
            {
                LowerTail->next=cur;
                LowerTail=LowerTail->next;
                cur=cur->next;
            }
            else 
            {
                GreaterTail->next=cur;
                GreaterTail=GreaterTail->next;
                cur=cur->next;
            }
        }
        GreaterTail->next=NULL;
        LowerTail->next=GreaterHead->next;
        pHead=LowerHead->next;
        free(GreaterHead);
        free(LowerHead);
        return pHead;
    }

7. 链表的回文结构。

题目链接
解题思路:根据回文结构关于中间结点的对称,那我们可以先找到中间结点,在将中间结点后面的结点逆序,最后将逆序后的结点和前面的结点进行比较,当存在一个不相等的时候,直接返回FALSE,循环结束则返回TRUE。

 struct ListNode* reverseList(struct ListNode* head){
    struct ListNode*new_head;
    new_head=(struct ListNode*)malloc(sizeof(struct ListNode));
    if(new_head==NULL)
    {
        exit(1);
    }
    new_head->next=NULL;
    struct ListNode*p=head;
    while(p)
    {
        struct ListNode*tmp=p->next;
        p->next=new_head->next;
        new_head->next=p;
        p=tmp;
    }
    head=new_head->next;
    free(new_head);
    return head;
    }
    struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode*slow,*fast;
    slow=fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}
    bool chkPalindrome(ListNode* head) {
        // write code here
        struct ListNode*p=head;
        struct ListNode*mid=middleNode(head);
        struct ListNode*mid_head=reverseList(mid);
        while(p&&mid_head)
        {
            if(p->val!=mid_head->val)
                return false;
            p=p->next;
            mid_head=mid_head->next;
        }
        return true;
    }

8. 输入两个链表,找出它们的第一个公共结点。

题目链接
解题思路:①先求两个链表的长度;②让长的链表先走差距步;③最后在一起走,相等就直接返回该结点的地址。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    int A=0;
    int B=0;
    struct ListNode *pa=headA;
    struct ListNode *pb=headB;
    while(pa)
    {
        A++;
        pa=pa->next;
    }
    while(pb)
    {
        B++;
        pb=pb->next;
    }
    if(pa!=pb)
        return NULL;
    pa=headA;
    pb=headB;
    int lenth=A-B;
    if(lenth>0)
    {
        for(int i=0;i<lenth;i++)
        {
            pa=pa->next;
        }
    }
    else if(lenth<0)
    {
        for(int i=0;i<-lenth;i++)
        {
            pb=pb->next;
        }
    }
    while(pb)
    {
        if(pa==pb)
            return pa;
        pa=pa->next;
        pb=pb->next;
    }
    return NULL;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/390613.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

延时任务的四种实现方式

什么是延迟任务&#xff1f;顾明思议&#xff0c;我们把需要延迟执行的任务叫做延迟任务。延迟任务的使用场景有以下这些&#xff1a;红包 24 小时未被查收&#xff0c;需要延迟执退还业务&#xff1b;每个月账单日&#xff0c;需要给用户发送当月的对账单&#xff1b;订单下单…

计算机网络之MAC和IP地址

MAC地址 在局域网中&#xff0c;硬件地址&#xff0c;又称为物理地址或MAC地址。 目前现在的局域网中实际上使用的都是6字节的MAC地址&#xff0c;所以每一个以太网设备都具有唯一的MAC地址。 MAC地址的格式 假设传输使用的是IP数据&#xff0c;V2的MAC帧较为简单&#xff…

Sonar:VSCode配置SonarLint/SonarLint连接SonarQube

需求描述 公司为项目代码配置了Sonar检测&#xff0c;希望在VSCode中开发项目时能够同步检测结果。 注意事项 SonarQube版本必须为7.9&#xff0c;否则SonarLint无法连接&#xff08;GitHub-SonarLint-Wiki第一行就有说明&#xff09;&#xff01;&#xff01;&#xff01;S…

【前端】一个更底层库-React基础知识点第2篇

目录属性状态PROPSPROP VALIDATIONSTATEFORMCONTROLLED COMPONENTSMIXINCOMPONENT APICOMPONENT LIFECYCLETOP API上一篇文章也是React基础知识点&#xff0c;了解到了React是什么&#xff1f;为什么要使用React&#xff1f;还知道了JSX概述&#xff0c;JSX嵌入变量&#xff0c…

python Django中的cookies和session会话保持技术

cookies和session都是为了保持会话状态而诞生的两个存储技术会话定义&#xff1a; 从打开浏览器访问一个网站&#xff0c;到关闭浏览器结束此次访问&#xff0c;称之为一次会话HTTP协议是无状态的&#xff0c;导致会话状态难以保持Cookies-定义 cookies是保存在客户端浏览器上的…

超简单的卷积和加法融合

神经网络的优化除了之前提到的一些硬件优化手段(AI硬件加速拾遗)之外&#xff0c;还有很多图层方面的优化手段。大家好啊&#xff0c;我是董董灿。 而且图层方面的优化&#xff0c;有时效果更佳。往往一个有效的优化&#xff0c;甚至可以“消除”掉一个算子的存在。 这里的“…

Vue组件-$refs、$nextTick和name属性的使用

Vue组件-$refs和$nextTick使用一、获取DOM二、$refs获取组件对象三、$nextTick异步更新DOM四、组件name属性的使用一、获取DOM 通过id或ref属性获取原生DOM 在mounted生命周期 – 2种方式获取原生DOM标签 目标标签 – 添加id / ref恰当时机, 通过id / 通过ref属性 获取目标标签…

Ubuntu系统新硬盘挂载

Ubuntu系统新硬盘挂载 服务器通常会面临存储不足的问题&#xff0c;大部分服务器都是ubuntu系统&#xff0c;该篇博客浅浅记载一下在ubuntu系统上挂载新硬盘的步骤。本篇博文仅仅记载简单挂载一块新的硬盘&#xff0c;而没有对硬盘进行分区啥的。如果需要更加完善的教程&#…

【C++】平衡二叉搜索(AVL)树的模拟实现

一、 AVL树的概念 map、multimap、set、multiset 在其文档介绍中可以发现&#xff0c;这几个容器有个共同点是&#xff1a;其底层都是按照二叉搜索树来实现的&#xff0c;但是二叉搜索树有其自身的缺陷&#xff0c;假如往树中插入的元素有序或者接近有序&#xff0c;二叉搜索树…

Java文档搜索引擎总结

Java文档搜索引擎总结项目介绍项目使用的技术栈前端页面展示后端逻辑部分索引部分搜索模块部分Web模块部分项目介绍 Java文档搜索引擎项目是一个SSM项目&#xff0c;该项目的前端界面部分是由搜索页面和展示页面组成&#xff0c;后端部分索引模块&#xff08;ScanAnalysis、in…

UNET 对 CARVANA 数据集的分割

目录 1. 介绍 2. UNET 网络 3. dataset 数据加载 4. utils 工具模块 4.1 get_loaders 函数 4.2 check_accuracy 函数 4.3 save_predictions_as_imgs 函数 4.4 完整代码 5. train 函数 5.1 关于导入的库文件 5.2 设置超参数 5.3 train_fn 训练一个epoch函数 5.4 m…

Redis是单线程还是多线程?Redis的10种数据类型,有哪些应用场景?

目录专栏导读一、同样是缓存&#xff0c;用map不行吗&#xff1f;二、Redis为什么是单线程的&#xff1f;三、Redis真的是单线程的吗&#xff1f;四、Redis优缺点1、优点2、缺点五、Redis常见业务场景六、Redis常见数据类型1、String2、List3、Hash4、Set5、Zset6、BitMap7、Bi…

【Java基础】30分钟Git 从入门到精通

一、 版本控制工具1、什么是版本控制系统&#xff1f;版本控制系统&#xff08;Version Control System&#xff09;:是一种记录一个或若干文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统。版本控制系统不仅可以应用于软件源代码的文本文件&#xff0c;而且可以对…

主成分分析(PCA)方法 和协方差 相关系数

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言1.主成分分析&#xff08;PCA&#xff09;方法2.算法步骤前言 主成分分析&#xff08;Principal Components Analysis&#xff0c;PCA&#xff09;是一种数据降…

Android工厂模式

工厂模式分为三种 :简单工厂模式 、工厂方法模式 、抽象工厂模式 。 目录 简单工厂模式 UML图 实现 使用场景&#xff1a; 优点 &#xff1a; 缺点&#xff1a; 工厂方法模式 UML图 实现 使用场景&#xff1a; 优点&#xff1a; 缺点&#xff1a; 抽象工厂模式 UM…

SpringCloud-负载均衡-Ribbon

文章目录1. 作用&#xff1a;负载均衡2. 应用实战2.1 provider-a代码2.2 provider-b代码2.3 consumer代码2.4 api工具向consumer发送请求查看对provider的调用情况3. ribbon总结3.1 Ribbon 源码核心3.2 如何实现负载均衡的呢&#xff1f;1. 作用&#xff1a;负载均衡 2. 应用实…

演唱会总是抢不到票?教你用Python制作一个自动抢票脚本

人生苦短 我用python 这个大家应该都知道吧&#xff1f; 是中国综合类现场娱乐票务营销平台&#xff0c; 业务覆盖演唱会、 话剧、音乐剧、体育赛事等领域。 如何快速抢票&#xff1f; 那么&#xff0c; 今天带大家用Python来制作一个自动抢票的脚本小程序 本文源码python安…

使用Java对稀疏数组的压缩与还原

稀疏矩阵的压缩与还原 稀疏数组中元素个数很少或者有大量的重复值&#xff0c;如果直接保存保存&#xff0c;会浪费很多空间&#xff0c;这时&#xff0c;就可以考虑对数组进行压缩存储。 先定义一个稀疏数组 //创建一个二维数组 11 * 11 int[][] array1 new int[11][11]; /…

Window 编辑、删除、新增右键菜单

关于 Window 右键菜单 右键菜单可以在注册表编辑器中新增和修改 建议先下载 registry-finder&#xff0c;查找速度更快&#xff01; 使用管理员模式打开 registry-finder 后&#xff0c;点击 HKEY_CLASSES_ROOT &#xff0c;修改注册表右键菜单的子路径如下表所示 类型路径…

49.在ROS中实现local planner(2)- 实现Purepersuit(纯跟踪)算法

48.在ROS中实现local planner&#xff08;1&#xff09;- 实现一个可以用的模板实现了一个模板&#xff0c;接下来我们将实现一个简单的纯跟踪控制&#xff0c;也就是沿着固定的路径运动&#xff0c;全局规划已经规划出路径点&#xff0c;基于该路径输出相应的控制速度 1. Pur…