单链表经典算法题理解

news2024/9/20 15:29:11

目录

1. 前言:

2. 移除链表元素

3.  反转链表

4. 合并两个有序链表

5. 链表的中间节点

6. 环形链表的约瑟夫问题

7. 分割链表


1. 前言:

当我们学习了单链表之后,我能可以尝试的刷一下题了,以下分享一下几道题的解法

2. 移除链表元素

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

思路:

我们这里可以通过创建一个新链表的形式,用来接收原链表里面不等于val的值,把他拿下来尾插,这里题目规定了原链表的值可能是0,就表示原链表是空链表,那我们进行判断,如果原链表为空,我们直接将原链表返回去,如果不为空,我们就进行遍历原链表,来判断原链表的值是否等于给定的val,然后拿下来在新链表中进行尾插操作,最后,判断一下新链表的尾是否是空的,如果不是空,我们需要将它手动置空,最后我们返回新链表的头即可。

代码

 typedef struct ListNode sln;//类型重命名,简化写法
struct ListNode* removeElements(struct ListNode* head, int val) {
    if(head == NULL)//如果链表为空,我们直接将原链表返回去
    {
        return head;
    }
    else
    {
        //我们创建新链表
        sln* newnode = NULL;
        sln* ptail = NULL;
        //创建一个指针用来遍历原链表
        sln*pcur = head;
        while(pcur)
        {
            //如果原链表里面的值不等于val,我们就拿下来尾插
            if(pcur->val != val)
            {
                //如果新链表为空,此时,这个链表的头和尾就都是拿下来的数据
                if(newnode == NULL)
                {
                    newnode = pcur;
                    ptail = pcur;
                }
                else
                {
                    //链表不为空,进行尾插
                     ptail->next = pcur;
                     ptail = ptail->next;
                }
            }
            pcur = pcur->next;
        }
        if(ptail)//这里判断,ptail是否是空节点,如果不是,我们需要将它指向空
        ptail->next = NULL;
        //返回新链表的头
        return newnode;
    }
}

3.  反转链表

题目:. - 力扣(LeetCode)

思路:

其实这里我们看到这个题目的时候,首先肯定是想到的是创建一个新链表,将原链表的节点拿下来一个个头插,但是这个方法写起来有点麻烦,我们这里用到一个新的方法来解,就是定义三个p1,p2和p3指针,分别指向空,头节点,和头节点下一个节点,将p2指向p1之后,将他们3个指针都往后移动,最后p2走到空了的话,p1此时就是头节点了,直接返回p1.

代码

 typedef struct ListNode sln;//类型重命名 简化写法
struct ListNode* reverseList(struct ListNode* head) {
   if(head == NULL)//判断链表是否为空
   {//如果为空直接返回原链表
    return head;
   }
   //定义三个指针,分别指向空,头节点和头节点下一个节点
   sln* p1 = NULL;
   sln* p2 = head;
   sln* p3 = head->next;
   while(p2)//当p2走到空了说明p1是头节点
   {
     p2->next = p1;
     p1 = p2;
     p2 = p3;
     if(p3 != NULL)//增加一个判断条件,如果p3走到空了,我们访问p3就会出错
        p3 = p3->next;
   }
   //直接返回p1
   return p1;
}

4. 合并两个有序链表

题目:. - 力扣(LeetCode)

思路:

这个题目,我能可以使用创建新链表的方式来解决,我们先创建一个新链表,然后再创建两个指针,分别用来遍历原链表里面的数据,如果1链表里的节点数据小于2链表里的节点数据,我们就把它拿下来尾插到新链表,反之将2链表里面的数据拿下来了尾插到新链表里面,

但是我们要考虑两种情况,就是如果1链表已经遍历完了,但是2链表里面还有数据,那么我们就将2链表里面的数据拿下来了尾插到新链表里面,反之将1链表里面的数据尾插到新链表中。

代码

 typedef struct ListNode sln;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if(list1 == NULL)
    {
        //如果list1为空链表,直接返回list2
        return list2;
    }
    if(list2 == NULL)
    {
        //如果list2为空链表,直接返回list1
        return list1;
    }
    //创建新链表
    sln* newnode = (sln*)malloc(sizeof(sln));
    sln* ptail = newnode;
    //定义两个指针,分别指向两个链表的头节点
    sln* p1 = list1;
    sln* p2 = list2;
    //循环遍历两个链表
    while(p1&&p2)
    {
        //如果p1<p2
        if(p1->val<p2->val)
        {//把p1拿下来尾插,p1向后走
            ptail->next = p1;
            ptail = ptail->next;
            p1 = p1->next;
        }
        else
        {//把p2拿下来尾插,p2往后走
            ptail->next =p2;
            ptail = ptail->next;
            p2 = p2->next;
        }
    }
    //可能p2走到空了,p1里面还有元素
    if(p1)
    {//拿下来尾插
        ptail->next = p1;
        ptail = ptail->next;
    }
    if(p2)//可能p1走到空了,p2里面还有元素
    {//拿下来尾插
        ptail->next =p2;
        ptail = ptail->next;
    }
    sln* ret = newnode->next;
    free(newnode);//动态申请的空间,手动释放
    newnode = NULL;
    return ret;
}

5. 链表的中间节点

题目:. - 力扣(LeetCode)

思路:

我们要找到链表的中间节点,我们可以采取计数器的方法,先遍历一遍链表,然后取计数器的中间值,在遍历一遍链表,返回中间值时的节点,这样也可以解题,但是需要遍历两遍链表,比较麻烦。那么我们就采取另一种方法。

快慢指针的方法。

我们定义两个指针,让他们遍历链表,但是两个指针的移动速度不一样,快指针一次走两步,慢指针一次走1步,这样,当快指针遍历完链表或者走到链表的尾节点时,此时慢指针就刚好走到链表的中间节点位置,直接返回慢指针指向的节点,这样就可以找到链表的中间节点了

代码:

 typedef struct ListNode sln;
struct ListNode* middleNode(struct ListNode* head) {
    //我们定义两个指针
    sln* slow = head;
    sln* fast = head;
    while(fast&&fast->next!=NULL)
    {
        //让这两个直接按照不同的速度往后走
        //2*slow = fast
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

6. 环形链表的约瑟夫问题

题目: 环形链表的约瑟夫问题_牛客题霸_牛客网

什么是约瑟夫问题呢?

来自百度:

 思路:

这里,我们知道报到指定数目,指定数目的人就要离开,我们首先需要定义一个计数器,然后我们需要使用到两个指针,一个指针用来遍历链表,一个指针记录住遍历链表的指针的上一次节点,然后循环遍历链表,直到链表只剩最后一个节点,跳出循环,返回最后一个节点里面的值就可以了。

代码:

 typedef struct ListNode sln;
//创建节点
 sln* BuyNode(int x)
 {
    sln* newnode = (sln*)malloc(sizeof(sln));
    if(newnode == NULL)
    {
        perror("malloc");
        exit(1);
    }
    newnode->val = x;
    newnode->next = NULL;
    return newnode;
 }
 //创建带环链表
 sln * CircleNode(int x)
 {
    sln* newnode = BuyNode(1);
    sln* ptail = newnode;
    for(int i = 2;i <= x;i++)
    {
        ptail->next = BuyNode(i);
        ptail = ptail->next;
    }
    ptail->next = newnode;
    return ptail;
 }

int ysf(int n, int m ) {
    //创建一个指针指向头节点
    sln*prev = CircleNode(n);
    //创建一个指针指向头节点的前一个节点
    sln*phead = prev->next;
    // write code here
    int count = 1;//定义计数器
    while(phead->next!= phead)//链表如果只有一个节点就跳出循环
    {
        if(count == m)//当计数器==给定数目时,需要删除节点
        {
            prev->next = phead->next;
            free(phead);
            phead = prev->next;
            count = 1;
        }
        else //不==,让两个指针都往后,计数器++
        {
            prev = phead;
            phead = phead->next;
            count++;
        }       
    }
    //返回最后一个节点里面的数据
    return phead->val;
}

7. 分割链表

题目:. - 力扣(LeetCode)

思路:

这里我们可以采取创建两个新链表的形式,一个用来接收小于x的节点,另一个用来接收大于或等于x的节点。然后将两个链表首尾链接的方式,并且将用头节点连接的尾节点指向空。

代码:

typedef struct ListNode sln;
struct ListNode* partition(struct ListNode* head, int x){
  if(head == NULL)//判断原链表是否为空
  {
    return head;
  }
  //创建一个指针来遍历原链表
  sln*pcur = head;
  //这里创建一个大链表来就收原链表大于x的节点
  sln*large = (sln*)malloc(sizeof(sln));
  sln* ptail = large;
  //创建一个小链表来接收原链表小于x的节点
  sln* little = (sln*)malloc(sizeof(sln));
  sln*pend = little;
  while(pcur)
  {
    if(pcur->val<x)
    {
        pend->next = pcur;
        pend = pend->next;
    }
    else
    {
        ptail->next = pcur;
        ptail = ptail->next;
    }
    pcur = pcur->next;
  }
  //遍历完原链表
  //将大小链表连接,将大链表尾节点指向空
  ptail->next = NULL;
   pend->next =large->next;
  //释放申请的空间
  sln*ret = little->next;
  free(little);
  free(large);
  little = large = NULL;
  return ret;
}

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

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

相关文章

ElementUI之el-table标题列中显示el-tooltip

ElementUI之el-table标题列中显示el-tooltip 文章目录 ElementUI之el-table标题列中显示el-tooltip1. el-table标题列中显示el-tooltip2. 实现代码3. 展示效果 1. el-table标题列中显示el-tooltip 在el-table-column标签内添加具名插槽v-slot:header 在el-tooltip标签中使用具…

《TCP/IP网络编程》(第十二章)I/O复用(2)

下面是基于I/O复用的回声服务器端和客户端代码 Linux系统 服务器端代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> // POSIX标准定义的通用函数&#xff0c;如close() #include <arpa/inet.h> // 提…

JVM(四)

在上一篇中&#xff0c;介绍了JVM组件中的运行时数据区域&#xff0c;这一篇主要介绍垃圾回收器 JVM架构图&#xff1a; 1、垃圾回收概述 在第一篇中介绍JVM特点时&#xff0c;有提到过内存管理&#xff0c;即Java语言相对于C&#xff0c;C进行的优化&#xff0c;可以在适当的…

DiskCatalogMaker for Mac:您的磁盘目录管理专家

对于需要管理大量磁盘文件的用户来说&#xff0c;DiskCatalogMaker for Mac无疑是一款不可或缺的工具。这款专为Mac用户设计的磁盘目录制作软件&#xff0c;以其简洁的操作界面和强大的功能&#xff0c;帮助您轻松创建和管理磁盘目录。 DiskCatalogMaker支持多种磁盘格式&…

最长递增子序列,交错字符串

第一题&#xff1a; 代码如下&#xff1a; int lengthOfLIS(vector<int>& nums) {//dp[i]表示以第i个元素为结尾的最长子序列的长度int n nums.size();int res 1;vector<int> dp(n, 1);for (int i 1; i < n; i){for (int j 0; j < i; j){if (nums[i]…

R语言入门 | 使用 ggplot2 进行数据可视化

1.0准备工作 先下好tidyverse包&#xff0c;并进行加载。 install.packages ( "tidyverse" ) library(tidyverse) R 包只需安装一次&#xff0c;但每次开始新会话时都要重新加载。 1.1 数据框 数据框是变量&#xff08;列&#xff09;和观测&#xff08;行&#x…

高级数据结构-并查集

例题1&#xff1a; Alice和Bob玩了一个古老的游戏&#xff1a;首先画一个 &#x1d45b;&#x1d45b; 的点阵&#xff08;下图 n3 &#xff09;。 接着&#xff0c;他们两个轮流在相邻的点之间画上红边和蓝边&#xff1a; 直到围成一个封闭的圈&#xff08;面积不必为 1&#…

Leecode热题100--二分查找---33:搜索旋转排序矩阵

题目&#xff1a; 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 给你 旋转后 的数组 nums 和一个整数 target &#xff0c;如果 nums 中存在这个目标值 target &#xff0c;则返回它的下标&#xff0c;否则返回 -1 。 思路&#xff1a; 此处采用容易理解的两次…

Make-An-Audio——用于语音生成的提示增强扩散模型

0.引言 论文提出了一个从文本生成语音的扩散模型 Make-An-Audio。该模型将文本提示作为输入&#xff0c;并据此生成语音。例如&#xff0c;输入 “一只猫在喵喵叫&#xff0c;一个年轻女人的声音”&#xff0c;就会输出猫在喵喵叫&#xff0c;一个女人在说话的音频。这项研究已…

php反序列化初步了解

一、定义 序列化&#xff08;串行化&#xff09;&#xff1a;将变量转换为可保存或传输的字符串的过程&#xff08;通常是字节流、JSON、XML格式&#xff09; 反序列比&#xff08;反串行化&#xff09;&#xff1a;把这个字符串再转化成原始数据结构或对象&#xff08;原来的…

一个生动的例子——通过ERC20接口访问Tether合约

生动的例子 USDT&#xff1a;符合ERC20标准的美元稳定币&#xff0c;Tether合约获得测试网上Tether合约地址通过自己写的ERC20接口访问这个合约 Tether合约地址&#xff1a;0xdAC17F958D2ee523a2206206994597C13D831ec7 IERC20.sol // SPDX-License-Identifier: GPL-3.0pra…

HTTP Basic Access Authentication Schema

HTTP Basic Access Authentication Schema 背景介绍流程安全缺陷参考 背景 本文内容大多基于网上其他参考文章及资料整理后所得&#xff0c;并非原创&#xff0c;目的是为了需要时方便查看。 介绍 HTTP Basic Access Authentication Schema&#xff0c;HTTP 基本访问认证模式…

代码随想录训练营Day 43|力扣343. 整数拆分、96.不同的二叉搜索树

1.整数拆分 代码随想录 视频讲解&#xff1a;动态规划&#xff0c;本题关键在于理解递推公式&#xff01;| LeetCode&#xff1a;343. 整数拆分_哔哩哔哩_bilibili 代码&#xff1a; class Solution { public:int integerBreak(int n) {// dp[i] 拆分数字i所获得的最大乘积为d…

7-zip工具?这么好用的你都能找到!

关于7-Zip&#xff0c;这不是一个神奇的小工具吗&#xff1f;让我悄悄告诉你&#xff0c;它其实是个压缩界的隐形冠军哦。 想象一下&#xff0c;你下载了一堆文件&#xff0c;电脑空间却告急&#xff0c;这时候7-Zip就像你的小助手&#xff0c;帮你把文件们“瘦身”&#xff0…

JavaScript-JavaWeb

目录 什么是JavaScript? js引入方式 js基础语法 书写语法 变量 数据据类型 运算符 类型转换 流程语句 js函数 js对象 1.Array 2.String 3.JSON js事件监听 什么是JavaScript? ● JavaScript(简称:JS)是一门跨平台、面向对象的脚本语言。是用来控制网页行为的,它能…

LeetCode2336无限集中的最小数字

题目描述 现有一个包含所有正整数的集合 [1, 2, 3, 4, 5, …] 。实现 SmallestInfiniteSet 类&#xff1a;SmallestInfiniteSet() 初始化 SmallestInfiniteSet 对象以包含 所有 正整数。int popSmallest() 移除 并返回该无限集中的最小整数。void addBack(int num) 如果正整数 …

Kong网关的负载均衡

安装java环境 查询 java安装包 196 yum list java* 安装java8197 yum install -y java-1.8.0-openjdk.x86_64 检验java8是否安装成功。198 java -version2个tomcat准备 另外一个tomcat区别在于&#xff1a;配置文件。conf/server.xml 启动tomcat [rootlocalhost bin]# ./…

如何在.htaccess文件创建一个自定义404页面

本周有一个客户&#xff0c;购买Hostease的虚拟主机&#xff0c;询问我们的在线客服&#xff0c;如何在.htaccess文件创建一个自定义404页面&#xff1f;我们为用户提供相关教程&#xff0c;用户很快解决了遇到的问题。在此&#xff0c;我们分享这个操作教程&#xff0c;希望可…

手摸手教你uniapp原生插件开发

行有余力,心无恐惧 这篇技术文章写了得有两三个礼拜,虽然最近各种事情,工作上的生活上的,但是感觉还是有很多时间被浪费.还记得几年前曾经有一段时间7点多起床运动,然后工作学习,看书提升认知.现在我都要佩服那会儿的自己.如果想回到那种状态,我觉得需要有三个重要的条件. 其…

错误记录:从把项目从Tomcat8.5.37转到Tomcat10.1.7

错误信息&#xff1a;在本地Servlet项目里没有报错&#xff0c;但是浏览器跳转该servlet时报错 型 异常报告 消息 实例化Servlet类[com.wangdao.lx.MyServlet1]异常 描述 服务器遇到一个意外的情况&#xff0c;阻止它完成请求。 例外情况 jakarta.servlet.ServletExceptio…