数据结构之链表经典算法QJ题目

news2024/12/29 1:10:08

目录

    • 单链表经典算法题目
      • 1. 单链表相关经典算法OJ题:移除链表元素
        • 思路一:
        • 思路二:
      • 2. 单链表相关经典算法QI题:链表的中间节点
        • 思路一
        • 思路二
      • 3. 单链表相关经典算法QJ题:反转链表
        • 思路一
        • 思路二
      • 4. 单链表相关经典算法QJ题:合并两个有序链表
        • 思路
      • 5. 循环链表经典应用:环形链表的约瑟夫问题
        • 思路
      • 6. 单链表相关经典算法 QJ题:分割链表
        • 思路

单链表经典算法题目

1. 单链表相关经典算法OJ题:移除链表元素

题目路径(点击练习):

题目:
在这里插入图片描述

思路一:

遍历原链表,遇到val就执行删除val节点的操作

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val) {
    
		//当链表的头结点的值为val时
       while(head && head->val==val)
    {
        head = head->next;
    }
    //当链表为空的时候,直接返回
     if (head == NULL) {
        return head;
    }   
      
    struct ListNode* pre = head;//定义临时指针指向与head一致

   
     while (pre->next)
    {
    	 //当链表指向的下一个节点的值为val
        if (pre->next->val == val) {
            pre->next = pre->next->next;   
        } else {
            /* 没找到,则继续遍历查找 */
            pre = pre->next;
        }
    }
    return head;
}



思路二:

定义新链表,遍历原链表找不为val的节点,尾插在新链表中

在这里插入图片描述

链表为空:插入进来的节点就是链表的头结点和尾结点

链表不为空:插入进来的节点就是新的尾结点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* removeElements(struct ListNode* head, int val) {
    struct ListNode* newHead = NULL;
    struct ListNode* newtail = NULL;
    struct ListNode* pcur = head;

    while(pcur)
    {
        //当原链表pcur的val不为查找的val时,将此节点尾插到新节点中,否则就继续往下走
        if(pcur->val != val)
        {
            //当链表为空
            if(newHead == NULL)
            {
                newHead = newtail = pcur;
            }else{
                //链表不为空
                newtail->next = pcur;
                newtail = newtail->next;
            }
        }
        pcur = pcur->next;
    }

    if(newtail)
        {
            newtail->next=NULL;
        }
    return newHead;
}

2. 单链表相关经典算法QI题:链表的中间节点

题目路径(点击练习)

题目

在这里插入图片描述

思路一

使用循环遍历统计链表中的个数

使用for循环根据除以2结果走到中间节点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* middleNode(struct ListNode* head) {
    struct ListNode* pre= head;
    int flag = 0;//用于计数
    while(pre)
    {
        flag++;//统计链表的个数
        pre=pre->next;
    }
    
   int mid = flag/2;//获取中间的位置
   pre=head;
   for(int i=0;i<mid;i++)
   {
       pre=pre->next;
   }
    return pre;
}
思路二

根据快慢指针

先定义两个指针
slow指针每走一步
fast指针每走两步

当fast->next 为空,则slow刚好指向的就是中间节点

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* middleNode(struct ListNode* head) {  
    //定义两个指针
    struct ListNode* slow = head;
    struct ListNode* fast = head;

    while(fast&&fast->next)
    {
        slow = slow->next;//一次走一步
        fast = fast->next->next;//一次走两步。当fase走完的时候slow指向的就是中间的节点
    }
    return slow;
}

3. 单链表相关经典算法QJ题:反转链表

题目路径(点击练习)

题目:

在这里插入图片描述

思路一

简单迭代

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* reverseList(struct ListNode* head) {
   //定义两个指针
   struct ListNode* temp = NULL;
   struct ListNode* curr = NULL;
   //循环遍历head
    while(head){
        temp = head->next;
        head->next = curr;
        curr = head;
        head = temp;//head和temp已被事实上置空了,防止跑飞
    }
    return curr;

}
思路二

创建三个指针

分别记录前驱结点,当前节点,后继节点,改变原链表指针方向
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* reverseList(struct ListNode* head) {
    //处理空链表
    if(head==NULL)
    {
        return head;
    }
    
    //创建三个指针,分别记录前驱节点,当前节点以及后继节点
    struct ListNode* n1 = NULL;
    struct ListNode* n2 = head;
    struct ListNode* n3 = head->next;

    while(n2)
    {
        n2->next = n1;

        n1 = n2;
        n2 = n3;
        if(n3)
        {
            n3 = n3->next;
        }
    }
 return n1;
}

4. 单链表相关经典算法QJ题:合并两个有序链表

题目路径(点击练习)

题目

在这里插入图片描述

思路

在两个原链表中创建两个指针l1,l2
再创建一个新链表

l1和l2相比较,较小值的放入新链表中
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {

    //当list1为空时直接返回list2
   if(list1 == NULL)
   {
       return list2;
   }
   //同理
   if(list2 == NULL)
   {
       return list1;
   }

   struct ListNode* l1 = list1;
   struct ListNode* l2 = list2;

   struct ListNode* newHead = NULL;
   struct ListNode* newTail = NULL;


   while(l1 && l2)
   {
       //当l1<l2
       if(l1->val < l2->val)
       {
           //判读链表是否为空
           if(newHead == NULL)
           {
               newHead = newTail = l1;
           }else{
               newTail->next = l1;
               newTail = newTail->next;
           }
           l1 = l1->next;
       }//l2<l1
       else{
           if(newHead == NULL)
           {
               newHead = newTail = l2;
           }else{
               newTail->next = l2;
               newTail = newTail->next;
           }
           l2=l2->next;
       }
       
   }
      //跳出循环时,出现两种情况l1为空,或者l2为空
      if(l1)
      {
          newTail->next = l1;
      }
      if(l2)
      {
          newTail->next = l2;
      }

   return newHead;
}

但是我们可以看到,上述出现了重复的代码,如何优化解决呢?

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 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;
   }

    ListNode* l1 = list1;
    ListNode* l2 = list2;

   ListNode* newHead,*newTail;//申请一块哨兵位
   newHead=newTail=(ListNode*)malloc(sizeof(ListNode));
   while(l1 && l2)
   {
       //当l1<l2
       if(l1->val < l2->val)
       {
           newTail->next = l1;
           newTail = newTail->next;
           l1 = l1->next;
       }//l2<l1
       else{
           newTail->next = l2;
           newTail = newTail->next;
           l2=l2->next;
       }
       
   }
      //跳出循环时,出现两种情况l1为空,或者l2为空
      if(l1)
      {
          newTail->next = l1;
      }
      if(l2)
      {
          newTail->next = l2;
      }

      
    //malloc开辟了空间,但是这块空间用不了得释放掉
    ListNode* ret = newHead->next;
    free(newHead);  

   return ret;
}

5. 循环链表经典应用:环形链表的约瑟夫问题

著名的Josephus问题 据说著名犹太 Josephus有过以下的故事:
~
在罗⻢⼈占领乔塔帕特后,39 个犹太⼈与Josephus及他的朋友躲到⼀个洞中,39个犹太⼈决定宁愿死也不要被⼈抓到,于是决定了⼀个⾃杀 ⽅式,41个⼈排成⼀个圆圈,由第1个⼈开始报数,每报数到第3⼈该⼈就必须⾃杀,然后再由下⼀ 个重新报数,直到所有⼈都⾃杀⾝亡为⽌。 历史学家
然⽽Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与⾃⼰安排在 第16个与第31个位置,于是逃过了这场死亡游戏。

题目

题目路径(点击练习)

在这里插入图片描述

思路

根据n来创建不带头单向链表
逢m删除当前节点

在这里插入图片描述

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param n int整型 
 * @param m int整型 
 * @return int整型
 */

 typedef struct ListNode ListNode;

 ListNode* BuyNode(int x)
 {
    ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
    newnode->val = x;
    newnode->next = NULL;
    return newnode;
 }

 ListNode* createList(int n)
 {
    ListNode* phead = BuyNode(1);
    ListNode* ptail = phead;
    for(int i = 2;i<=n;i++)
    {
        ptail->next=BuyNode(i);
        ptail = ptail->next;
    }
    //链表要首尾相连使其循环起来
    ptail->next = phead;
    return phead;
 }
int ysf(int n, int m ) {
    //根据n来创建不带头单向链表
    ListNode* head = createList(n);
    ListNode* pcur = head;
    ListNode* prev = NULL;
    int count = 1;
    //逢m删除当前节点
    while(pcur->next != pcur)
    {
       if(count == m)
       {
        //删除当前节点
        prev->next = pcur->next;
        free(pcur);
        pcur = prev->next;
        count = 1;

       }else{
        prev = pcur;
        pcur = pcur->next;
        count++;
       }
    }
    //此时,节点便是唯一幸存下来的
    return pcur->val;
}

6. 单链表相关经典算法 QJ题:分割链表

题目路径(点击练习)

题目

在这里插入图片描述

思路

定义两个链表:大链表和小链表,遍历原来的节点将其放入对应的新链表中,最后将大链表和小链表的首尾相连

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode ListNode;
struct ListNode* partition(struct ListNode* head, int x){
    //小链表
    ListNode* lessHead,*lessTail;
    lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode));//创建哨兵位

    //大链表
    ListNode* greaterHead,*greaterTail;
    greaterHead = greaterTail = (ListNode*)malloc(sizeof(ListNode));//创建哨兵位

    ListNode* pcur = head;

    while(pcur)
    {
        if(pcur->val < x)
        {
            lessTail->next = pcur;
            lessTail = lessTail->next;
        }else{
            greaterTail->next = pcur;
            greaterTail = greaterTail->next;
        }
        pcur = pcur->next;
    }
    
    greaterTail->next = NULL;
    lessTail->next = greaterHead->next;

    ListNode* ret = lessHead->next;
    free(lessHead);
    free(greaterHead);
    return ret;
}

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

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

相关文章

pytest 框架自动化测试

随笔记录 目录 1. 安装 2. 安装pytest 相关插件 2.1 准备阶段 2.2 安装 2.3 验证安装成功 3. pytest测试用例的运行方式 3.1 主函数模式 3.1.1 主函数执行指定文件 3.1.2 主函数执行指定模块 3.1.3 主函数执行某个文件中的某个类、方法、函数 3.1.4 主函数执行生…

学习鸿蒙背后的价值?星河版开放如何学习?

现在是2024年&#xff0c;华为在1月18开展了鸿蒙千帆起仪式发布会。宣布了鸿蒙星河版&#xff0c;并对开发者开放申请&#xff0c;此次发布会主要是说明了&#xff0c;鸿蒙已经是全栈自研底座&#xff0c;鸿蒙星河版本的编程语言改为ArkTS/仓颉&#xff0c;内核改为鸿蒙原生内核…

操作系统虚拟内存(上)

一、虚拟内存简要 1.为什么需要虚拟内存? 如果第一个程序在 2000 的位置写入一个新的值&#xff0c;将会擦掉第二个程序存放在相同位置上的所有内容&#xff0c;所以同时运行两个程序是根本行不通的&#xff0c;这两个程序会立刻崩溃&#xff0c;所以想要在这种情况下&#…

SQL 练习题目(入门级)

今天发现了一个练习SQL的网站--牛客网。里面题目挺多的&#xff0c;按照入门、简单、中等、困难进行了分类&#xff0c;可以直接在线输入SQL语句验证是否正确&#xff0c;并且提供了测试表的创建语句&#xff0c;也可以方便自己拓展练习&#xff0c;感觉还是很不错的一个网站&a…

OpenAI 的 GPTs 提示词泄露攻击与防护实战:防御卷(一)

前面的OpenAI DevDay活动上&#xff0c;GPTs技术的亮相引起了广泛关注。随着GPTs的创建权限开放给Plus用户&#xff0c;社区里迅速涌现了各种有趣的GPT应用&#xff0c;这些都是利用了Prompt提示词的灵活性。这不仅展示了技术的创新潜力&#xff0c;也让人们开始思考如何获取他…

Java 面向对象进阶 15 接口(黑马)

案例&#xff1a; 代码&#xff1a; Animal类代码&#xff1a; public abstract class Animal {private String name;private int age;public Animal() {}public Animal(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public…

揭秘H5与小程序的测试奥秘!

最近接触了较多关于H5页面的测试&#xff0c;H5页面的测试除了业务逻辑功能测试外&#xff0c;其他部分的测试方法基本是可以通用的&#xff0c;在此对H5页面和小程序的一些通用测试方法进行总结分享给大家。 H5优势 H5可以跨平台&#xff0c;开发成本相对较低&#xff1b; H…

洛谷p1002过河卒

[NOIP2002 普及组] 过河卒 题目描述 棋盘上 A A A 点有一个过河卒&#xff0c;需要走到目标 B B B 点。卒行走的规则&#xff1a;可以向下、或者向右。同时在棋盘上 C C C 点有一个对方的马&#xff0c;该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为…

having子句

目录 having子句 having和where的区别 Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 现在要求查询出每个职位的名称&#xff0c;职位的平均工资&#xff0c;但是要求显示平均工资高于 200 的职位 按照职位先进行分组&#xff0c;同…

2000-2022年各省城乡收入差距泰尔指数数据(原始数据+计算过程+结果)

2000-2022年各省城乡收入差距泰尔指数数据&#xff08;原始数据计算过程结果&#xff09; 1、时间&#xff1a;2000-2022年 2、指标&#xff1a;地区、居民可支配收入&#xff08;元&#xff09;、农村家庭可支配&#xff08;元&#xff09;、城市家庭可支配&#xff08;元&a…

Java线程基础知识和使用

目录 什么是线程 Java中线程的使用 线程的实现 并运行一个线程 如何为线程命名 查看当前jvm中运行的所有线程 线程池的基本使用 线程休眠 设置线程的优先级&#xff08;都仅供参考&#xff09; 线程的插队 线程的中断 线程的分类 线程的状态 什么是线程 线程是操…

Walmart 砸23亿美元收购 Vizio | 百能云芯

美国零售巨头沃尔玛&#xff08;Walmart&#xff09;宣布以 23 亿美元的价格收购智能电视品牌 Vizio&#xff0c;该举措旨在加速其广告业务 Walmart Connect 的增长。市场研究机构 TrendForce 看好此收购案&#xff0c;认为这有助于 Vizio 挑战三星的地位&#xff0c;成为美国第…

一个诗词网站的设计与实现

诗词网 0、前言 ​  前段时间非常喜欢诗词&#xff0c;又恰逢想开发一个社区类的系统&#xff0c;于是便有将两者结合起来的构想&#xff0c;说干就干&#xff0c;便有了诗词网&#xff08;诗词社区系统&#xff09;这个项目。 ​  由于是利用空闲时间进行开发&#xff0c…

更高效的构建工具-vite

更高效的构建工具-vite 前言Vite是什么Vite和webpack的比较1. 运行原理2. 使用成本 Vite的初体验 前言 首先我们要认识什么时构建工具&#xff1f; 企业级项目都具备什么功能呢&#xff1f; Typescript&#xff1a;如果遇到ts文件&#xff0c;我们需要使用tsc将typescript代码…

百度智能云分布式数据库 GaiaDB-X 与龙芯平台完成兼容认证

近日&#xff0c;百度智能云的分布式关系型数据库软件 V3.0 与龙芯中科技术股份有限公司的龙芯 3C5000L/3C5000 处理器平台完成兼容性测试&#xff0c;功能与稳定性良好&#xff0c;获得了龙架构兼容互认证证书。 龙芯系列处理器 通用 CPU 处理器是信息产业的基础部件&#xf…

Mac远程连接Windows 11

1. Windows配置 1.1 打开远程连接权限 打开“控制面板”搜索“远程”&#xff0c;选择“允许远程访问你的计算机”这一项。 1.2 添加远程连接用户 打开“计算机管理”&#xff0c;并在用户下新增“新用户”&#xff0c;share是我自己使用的名字&#xff0c;这个名字不固定随…

CSP-J 2023 T3 一元二次方程

文章目录 题目题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 题目传送门题解思路总代码 提交结果尾声 题目 题目背景 众所周知&#xff0c;对一元二次方程 a x 2 b x c 0 , ( a ≠ 0 ) ax ^ 2 bx c 0, (a \neq 0) ax2bxc0,(a0)&#xff0c;可…

关于dxf文件中,多段线凸度的计算

1.前言 在前面的CAD中的dxf文件解析(二)中讲到了一些CAD的dxf文件解析点、线、圆弧、圆、块等的思路。下面提供链接&#xff1a; &#xff08;二): CAD中的dxf文件解析(二):dxflib的使用_不爱学习 未完待续的博客-CSDN博客_dxflib (一)&#xff1a;CAD中的dxf文件解析(一):准备…

2024.2.22 C++QT 作业

思维导图 练习题 1>完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面。如果账…

如何将 .NET Aspire 应用程序部署到 Azure Container App

作者&#xff1a;Jiachen Jiang 排版&#xff1a;Alan Wang 最近发布的用于构建云原生应用程序的 .NET Aspire 与 Azure Container App&#xff08;ACA&#xff09;非常匹配。.NET Aspire 旨在轻松管理由一系列相互依赖的微服务组成的应用程序。Azure Container App 专为微服务…