大厂面试经典单链表例题(创建有序单链表,逆置单链表,判断链表是否有环,取链表中间节点)(含核心代码与解析)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 大厂面试经典单链表例题(创建有序单链表,逆置单链表,判断链表是否有环,取链表中间节点)(含核心代码与解析)

目录


引言

创建有序单链表

题目

算法思路

代码实现

逆置单链表

题目

算法思路

代码实现

判断单链表是否有环

题目

算法思路

代码实现

取单链表中间节点的数值

题目

算法思路

代码实现

总结


引言


有关单链表的基础操作,如动态分布空间,单链表创建的思路,单链表的增、删、改、毁,笔者已经在博客中详细解析了,有兴趣的小伙伴也可以取看看,

本次介绍的是有关单链表的四道大厂面试典中典,其中的逆置单链表更是重量级,大家放心食用😁


正文


创建有序单链表


题目


创建一个升序或降序的单链表,并打印输出,例如:

输入: 1 5 6 2 3
输出: 1 2 3 5 6


算法思路


算法思路:

       s1:每获得一个数据 就创建一个数据结点

       s2:把数据写入到数据结点中去

       s3:把写好的数据结点加入到链表中去

           分情况讨论:

               从无到有

               从少到多

                   头插法

                   尾插法

                   中间插入

我们将算法思路待人代码中观察


代码实现


Node *create_sort_list()
{
  u4 d;
  Node *pnew = NULL;    //指向 新创建的节点
  Node *head = NULL;
  while(1)
  {
    scanf("%d",&d);
    if(d == 0)        //约定输入0,结束输入
      break;
    pnew = malloc(sizeof(*pnew));    //分配空间
    pnew->data = d;                  //将数据写入数据节点
    pnew->next = NULL;
        //将写好的数据节点加入到链表
    if(head == NULL)                 //从无到有
    {
      head = pnew;
    }
    else                             //从少到多
    {
      Node *p = head;
      Node *pre = NULL;
      while(p)                     //找出链表中比新节点大的数据打的节点
      {
        if(p->data > pnew->data)    //找到就返回这个节点
        {
          break;
        }
        else                        //没找到就往下遍历,直到p==NULL,即新节点的值是最大的,插到末尾
        {
          pre = p;
          p = p->next;
        }
      }
      if(p != NULL)
      {
        if(p == head)            //头插法
        {
          pnew->next = head;   //新节点指向链表的第一个,即指向head
              head = pnew;     //然后将head指向新节点
        }
        else                     //插入中间
        {
          pnew->next = p;
          pre->next = pnew;
        }
      }
      else                         //插到末尾
      {
        pre->next = pnew;
      }
    }
  }
  return head;
}


逆置单链表


题目


就地逆置一个链表(不允许申请新的结点空间)

   例子:

       h: 1 5 3 4

       =>

       h: 4 3 5 1

       要求:

           不允许申请新的结点空间


算法思路


把原链表的每一个结点 ,摘下来 ,然后按头插法 加入到新链表。

 

Node *reverse(Node *h)
{
  //创建一个指向逆置后链表的第一个结点
  //创建一个指针p为遍历指针
  while(p)
  {
      //step 1:把h指向的链表的第一个结点摘下来
    //step2: 按照头插法 把p结点 加入到逆置后的链表first
    //step2.1 从无到有
    //step2.2 从少到多
  }
      //返回逆置链表的第一个节点
}


代码实现


Node *reverrse(Node *h)
{
  Node *first = NULL;        //创建一个指向逆置后链表的第一个结点
  Node *p = h;               //创建一个指针p为遍历指针
  while(p)
  {
        //step 1:把h指向的链表的第一个结点摘下来
    h = h->next;
    p->next = NULL;
        //step2: 按照头插法 把p结点 加入到逆置后的链表first
    //step2.1 从无到有
    if(first == NULL)
    {
      first = p;
    }
    else            //step2.2 从少到多
    {
      p->next = first;
      first = p;
    }
    p = h;
  }
  return first;        //返回逆置链表的第一个节点
}


判断单链表是否有环


题目


判断一个单链表是否有环


算法思路


快慢指针

定义两个指针p和q;

让p每次走两步,q每次走一步

当p和q相遇时则说明有环,否则就没有环。


代码实现


/*
is_a_ring:判断单链表是否有环
    @h:指定的单链表的第一个节点指针
    返回值:
        1 有环
        0 无环
 */
int is_a_ring(Node *h)
{
  Node *p = NULL;//fast指针
  Node *q = NULL;//slow指针
  p = h;
  q = h;
  while(p)
  {
    p = p->next;
    if(p == NULL)
    {
        break;
    }
    p = p->next;
    q = q->next;
    if(p == q)
    {
      return 1;
    } 
  }
  return 0;
}


取单链表中间节点的数值


题目


写一个程序,获取链表中间结点的值

       例子:

           对于奇数结点 返回中间结点值

           输入 :1 2 3 4 5

           输出:3

           对于偶数结点  返回较小下标的值

           输入: 25 69 78 45 96 -21 -47 62

           输出:45


算法思路


定义两个指针p和q;

让p每次走两步 q走一步

当p走到链表末尾时 此时q刚好走到链表的中间结点。


代码实现


void get_middle_v(Node *h)
{
  Node *pk = h;    //快指针
  Node *pm = h;    //慢指针
  while(1)
  {
    if(pk->next == NULL)    //快指针已经到了最后一个(奇数个)
    {
      printf("%d\n",pm->data);
      break;
    }
    else
    {
      pk = pk->next->next;        //快指针的下一个是最后一个(偶数个)
      if(pk == NULL)
      {
        printf("%d\n",pm->data);
        break;
      }
      pm = pm->next;
    }
  }
}


总结


这些题目其实总体难度不高,更重要的是体会其中的算法思路,分类思想,利用好单链表本身的空间余节点取解决问题。

相关文章
|
2月前
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
50 0
Leetcode第21题(合并两个有序链表)
|
16天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
45 2
|
2月前
|
存储 算法
【❤️算法笔记❤️】-每日一刷-21、合并两个有序链表
【❤️算法笔记❤️】-每日一刷-21、合并两个有序链表
95 0
|
17天前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
50 2
|
27天前
|
存储 NoSQL MongoDB
MongoDB面试专题33道解析
大家好,我是 V 哥。今天为大家整理了 MongoDB 面试题,涵盖 NoSQL 数据库基础、MongoDB 的核心概念、集群与分片、备份恢复、性能优化等内容。这些题目和解答不仅适合面试准备,也是日常工作中深入理解 MongoDB 的宝贵资料。希望对大家有所帮助!
|
1月前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
64 1
|
2月前
|
存储
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)(一)
【初阶数据结构】深入解析单链表:探索底层逻辑(无头单向非循环链表)
|
3月前
|
缓存 Android开发 开发者
Android RecycleView 深度解析与面试题梳理
本文详细介绍了Android开发中高效且功能强大的`RecyclerView`,包括其架构概览、工作流程及滑动优化机制,并解析了常见的面试题。通过理解`RecyclerView`的核心组件及其优化技巧,帮助开发者提升应用性能并应对技术面试。
99 8
|
3月前
|
存储 缓存 Android开发
Android RecyclerView 缓存机制深度解析与面试题
本文首发于公众号“AntDream”,详细解析了 `RecyclerView` 的缓存机制,包括多级缓存的原理与流程,并提供了常见面试题及答案。通过本文,你将深入了解 `RecyclerView` 的高性能秘诀,提升列表和网格的开发技能。
75 8

推荐镜像

更多