【数据结构(四)】链表经典练习题

news2025/9/19 20:26:14

❣博主主页: 33的博客❣
▶️文章专栏分类:数据结构◀️
🚚我的代码仓库: 33的代码仓库🚚
🫵🫵🫵关注我带你学更多数据结构知识

在这里插入图片描述

目录

  • 1.前言
  • 2.删除值为key的所有结点
  • 3.反转链表
  • 4.返回中间结点
  • 5.输出倒数第k个结点
  • 6.链表分割
  • 7.链表回文
  • 8.相交链表
  • 9.环形链表
    • 9.1是否为环形链表
    • 9.2入环第一个节点
  • 10.总结

1.前言

在上一篇文章中博主已经介绍了链表的基础知识,什么是链表,如何实现一个链表,以及LinkedList的操作方法,那么在这篇文章中通过一些链表的经典习题来练习吧。

2.删除值为key的所有结点

删除值为val的所有结点:OJ链接
解题思路:

1.遍历链表。
2.如果某个结点A的值等于key,那么A的前一个结点B的next值直接等于A的next。
3,继续遍历,遇到等于值等于key的重复上诉操作,直到全部遍历完成。

public void removeAllKey(int key) {
    if (head==null){
        return;
    }
    Node node=head;
    Node cur=head.next;
    while (cur!=null){
        if(cur.val==key){
            node.next=cur.next;
            cur=cur.next;
        }else {
            node=node.next;
            cur=cur.next;
        }
    }
    if(head.val==key){
        head=head.next;
    }
    }

3.反转链表

反转链表:OJ链接

public ListNode reverseList(ListNode head) {
        if(head==null||head.next==null){
            return head;
        }
        ListNode cur=head.next;
        head.next=null;
        while (cur!=null){
            ListNode curNext=cur.next;
            cur.next=head;
            head=cur;
            cur=curNext;
        }
        return head;
    }

4.返回中间结点

返回中间结点:OJ链接
方式一:
解题思路:

1.求链表的大小size
2.中间结点为size/2
遍历链表,走到size/2的位置,返回该节点

class Solution {
	//求链表长度
    public int size(ListNode head) {
        ListNode node=head;
        int count=0;
        while (node!=null){
           count++;
            node=node.next;
        }
        return count;
    }
    public ListNode middleNode(ListNode  head) {
        if(head==null||head.next==null){
            return head;
        }
        int Size=size(head);
        int middle=Size/2;
        ListNode node=head;
        for (int i=0;i<middle;i++){
            node=node.next;
        }
        return node;
    }    
}

方式二:
解题思路:

1.设置一个快结点:fast,设置一个慢结点:slow。
2.我们试想:如果fast的速度是slow的两倍,那么当fast到达路程的终点时,此时slow就走了路程的一半。
3.所以我们让fast每次走两步,slow每次走一步,当fast=null或者fast.next=null的时候,slow就是中间结点

public Node middleNode2() {
        Node fast=head;
        Node slow=head;
        while (fast!=null||fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
        }
        return slow;
    }

5.输出倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点:OJ链接
解题思路:

1。让fast先走k-1步数
2.再同时走,当fast到达终点时,那么它们就相差k
3.此时的slow就是倒数第k个结点

ublic Node FindKthToTail (int k) {
        Node fast=head;
        Node slow=head;
    if(k<=0||head==null){
        return null;
    }
    while (k-1>0){
        fast=fast.next;
        k--;
    }
    while (fast.next!=null){
        fast=fast.next;
        slow=slow.next;
    }
    return slow;
    }

6.链表分割

以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前:OJ链接
解题思路:

1.首先,遍历链表
2.再创建两个链表,一个用于存放小于x的值,另一个用于存放大于x的值
3.再把第一个链表的最后一个结点与第二个链表的头节点串起来。

public Node partition(int x) {
        if (head==null){
            return null;
        }
        Node as=null;
        Node ae=null;
        Node bs=null;
        Node be=null;
        Node cur=head;
        while (cur!=null){
            if (cur.val<x){
              if(as==null){
                  //插入第一个节点
                  as=cur;
                  ae=cur;
                  cur=cur.next;
              } else {
                  ae.next=cur;
                  ae=ae.next;
                  cur=cur.next;
              }
            }else {
             //cur.val>x
             if(bs==null){
             //插入第一个节点
                 bs=cur;
                 be=cur;
                 cur=cur.next;
             }  else {
                 be.next=cur;
                 be=be.next;
                 cur=cur.next;
             }
            }
        }
        //如果第一个链表为空就直接返回第二个链表的头节点
        if(as==null){
            return bs;
        }
        ae.next=bs;
        if(bs != null) {
            //第2个区间有数据
            be.next = null;
        }
        head=as;
        return head;
    }

7.链表回文

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构:OJ链接
解题思路:

1.查看链表是否回文,是指从前向后遍历,或者从后向前遍历,输出的之都相同。
2.我们可以先找到中间位置,再从中间位置进行翻转,使它同时从两头向中间遍历
3.遍历的时候如果如果链表有偶数个的情况,和有奇数个的情况是不一样的,当有奇数个时,走到相同的位置就停止,当有偶数个时,当下再走一步就相遇时就停止。

public boolean chkPalindrome() {
		 if(head == null || head.next == null) {
            return true;
        }
        //按照中间位置翻转链表
        //1.找到中间位置(middle已经在4中写过)
        Node middle=middleNode2();
        //2.翻转
        Node ehead=middle;
        Node cur=ehead.next;
        while (cur!=null){
            Node curNext=cur.next;
            cur.next=ehead;
            ehead=cur;
            cur=curNext;
        }
        //从两头开始遍历
        Node snode=head;
        Node enode=ehead;
        while (snode!=enode){
            if (snode.val!=enode.val){
                return false;
            }
            if (snode.next==enode){
                return true;
            }
                snode=snode.next;
                enode=enode.next;
        }
        return true;
    }

8.相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点:OJ链接
解题思路:

1.求两个链表的长度,再求长度差值
2.定义节点fast代表长的链表头节点,slow代表短的链表的头节点。先让长的链表先走差值步,再同时走。
3.两个链表相遇时就是相交节点。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {        
        ListNode nodeA=headA;
        ListNode nodeB=headB;
        int lenA=size(headA);
        int lenB=size(headB);
        ListNode fast=headA;
        ListNode slow=headB;
        int len=lenA-lenB;
        if(len<0){
            len=lenB-lenA;
            fast=headB;
            slow=headA;
        }
        while(len>0){
            fast=fast.next;
            len--;
        }
        while(fast!=slow&&fast!=null){
            fast=fast.next;
            slow=slow.next;
        }       
        return fast;      
    }

9.环形链表

9.1是否为环形链表

给你一个链表的头节点 head ,判断链表中是否有环:OJ链接
解题思路:

1.定义节点fast代表长的链表头节点,slow代表短的链表的头节点.
2.每次让fast走两步,slow走一步,如果是环形链表,那么它们一定会在环中的某一个位置相遇,否则不是环形链表
为什么每次让fast走两步,slow走一步?不可以fast走3步,4步吗?假设环中只有两个元素A,B,当slow进入环时在A的节点的位置,此时fast在B节点的位置,slow走一步就到B的位置,fast走3步就到A的位置,那么它们永远都不会相遇。
只有每次让fast走两步,slow走一步,换的长度为1,那么肯定会相遇。

 public boolean hasCycle(ListNode head) {
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null&&fast.next!=null){
            //fast.next!=null&&fast!=null,不能这样写
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                return true;
            }   
        }
        return false;       
    }

9.2入环第一个节点

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null:OJ链接
解题思路:

让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。
证明如下:

在这里插入图片描述

public class Solution {
    ListNode hasCycle(ListNode head) {
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null&&fast.next!=null){
            //fast.next!=null&&fast!=null,不能这样写
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                return fast;
            }   
        }
        return null;       
    }
    public ListNode detectCycle(ListNode head) {
          ListNode fast=hasCycle(head);
          if(fast==null){
            return null;
          }
          ListNode slow=head;
          while(fast!=slow){
            fast=fast.next;
            slow=slow.next;
          }
          return fast;  
    }
}

10.总结

本篇博客主要对链表的经典习题进行了讲解,同学们要理解解题的一些思想做到融会贯通,如果有疑惑的地方欢迎大家来和博主沟通,交流。

下期预告:栈

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

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

相关文章

C++11 设计模式1. 模板方法(Template Method)模式学习。UML图

一 什么是 "模板方法&#xff08;Template Method&#xff09;模式" 在固定步骤确定的情况下&#xff0c;通过多态机制在多个子类中对每个步骤的细节进行差异化实现&#xff0c;这就是模板方法模式能够达到的效果。 模板方法模式属于&#xff1a;行为型模式。 二 &…

Hive的分区与排序

一、Hive分区 1.引入&#xff1a; 在大数据中&#xff0c;最常见的一种思想就是分治&#xff0c;我们可以把大的文件切割划分成一个个的小的文件&#xff0c;这样每次操作一个个小的文件就会很容易了&#xff0c;同样的道理&#xff0c;在hive当中也是支持这种思想的&#xff…

SQL注入sqli_labs靶场第三题

?id1and 11 and 11和?id1and 11 and 11进行测试如果11页面显示正常和原页面一样&#xff0c;并且12页面报错或者页面部分数据显示不正常&#xff0c;那么可以确定此处为字符型注入。 根据报错信息判断为单引号带括号注入 联合查询&#xff1a; 猜解列名 ?id1) order by 3-…

实战项目——智慧社区(二)之 物业管理

分页 用于分页封装的实体类 Data public class PageVO {private Long totalCount;private Long pageSize;private Long totalPage;private Long currPage;private List list; }分页的相关配置 package com.qcby.community.configuration;import com.baomidou.mybatisplus.e…

利用Sentinel解决雪崩问题(二)隔离和降级

前言&#xff1a; 虽然限流可以尽量避免因高并发而引起的服务故障&#xff0c;但服务还会因为其它原因而故障。而要将这些故障控制在一定范围避免雪崩&#xff0c;就要靠线程隔离(舱壁模式)和熔断降级手段了&#xff0c;不管是线程隔离还是熔断降级&#xff0c;都是对客户端(调…

物联网实验

实验1 基于ZStack光敏传感器实验 1.实验目的 我们通过上位机发指令给协调器&#xff0c;协调器把串口接收到的指令通过Zigbee协议无线发送给带有光敏传感器的终端节点&#xff0c;获取到数据以后把数据返回给上位机&#xff0c;实现无线获取数据的目的。 2.实验设备 硬件&a…

Vue2和Vue3组件通信:父子与兄弟间的桥梁

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

Chatgpt掘金之旅—有爱AI商业实战篇|在线辅导业务|(十三)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 官方论坛&#xff1a; www.jingyuai.com 京娱AI 一、AI技术创业播客剧本写作服务有哪些机会&#xff1f; 人工智能&#xff08;AI&#xff09;技术作为当今科技创新的前沿领域&#xff0c;为创业者提供了广阔的机会和挑战。…

分类模型绘制决策边界、过拟合、评价指标

文章目录 1、线性逻辑回归决策边界1.2、使用自定义函数绘制决策边界1.3、三分类的决策边界1.4、多项式逻辑回归决策边界 2、过拟合和欠拟合2.2、欠拟合2.3、过拟合 3、学习曲线4、交叉验证5、泛化能力6、混淆矩阵7、PR曲线和ROC曲线 x2可以用x1来表示 1、线性逻辑回归决策边界 …

TQ15EG开发板教程:在MPSOC上运行ADRV9009

首先需要在github上下载两个文件&#xff0c;本例程用到的文件以及最终文件我都会放在网盘里面&#xff0c; 地址放在最后面。在github搜索hdl选择第一个&#xff0c;如下图所示 GitHub网址&#xff1a;https://github.com/analogdevicesinc/hdl/releases 点击releases选择版…

Vue 读取后台二进制文件流转为图片显示

Vue 读取后台二进制文件流转为图片显示 后台返回格式 <img :src"payImg" id"image" style"width: 150px;height: 150px;" alt"">axios写法 重点 responseType: ‘blob’ &#xff0c; 使用的是res中的data blob this.$axios.…

科学计算最新成果!基于多分支物理信息深度算子神经网络的快速通用热仿真模型...

热仿真在各个领域中起着至关重要的作用&#xff0c;通常涉及复杂的偏微分方程&#xff08;PDE&#xff09;仿真以进行热优化。为了解决通过传统方法求解复杂的偏微分方程所面临的挑战&#xff0c;我们利用神经网络进行热预测&#xff0c;尤其是采用深度神经网络作为PDE的通用求…

HTML5学习记录

简介 超文本标记语言&#xff08;HyperText Markup Language&#xff0c;简称HTML&#xff09;&#xff0c;是一种用于创建网页的标准标记语言。 编辑器 下载传送门https://code.visualstudio.com/ 下载编辑器插件 标题 标题通过 <h1> - <h6> 标签进行定义。 …

花样鼠标悬停特效

代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style&…

头歌-机器学习 第9次实验 随机森林

第1关&#xff1a;Bagging 任务描述 本关任务&#xff1a;补充 python 代码&#xff0c;完成 BaggingClassifier 类中的 fit 和 predict 函数。请不要修改 Begin-End 段之外的代码。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 什么是 Bagging&#xf…

python 有哪些函数

Python内置的函数及其用法。为了方便记忆&#xff0c;已经有很多开发者将这些内置函数进行了如下分类&#xff1a; 数学运算(7个) 类型转换(24个) 序列操作(8个) 对象操作(7个) 反射操作(8个) 变量操作(2个) 交互操作(2个) 文件操作(1个) 编译执行(4个) 装饰器(3个) …

PHP自助建站系统,小白也能自己搭建网站

无需懂代码&#xff0c;用 自助建站 做企业官网就像做PPT一样简单&#xff0c;您可以亲自操刀做想要的效果&#xff01; 自助建站是一款简单、快捷、高效的工具&#xff0c;可以帮助您制作响应式网站。我们的自助建站系统&#xff0c;将传统的编码工作转化为直观的拖拽操作和文…

功能测试_验证两个两位数整数边界数据的求和_边界值分析法

验证两个两位数整数边界数据的求和 上点&#xff1a;刚好等于边界的值 &#xff08;取值不考虑开闭区间&#xff09; 离点&#xff1a;刚好小于/大于边界上的值 &#xff08;取值类型看需求&#xff09; 内点&#xff1a;边界范围内的任何取值 &#xff08;取中间的值&#…

2024年 前端JavaScript 进阶 第4天 End 笔记

4.1-内容和浅拷贝 4.2-递归函数 4.3-深拷贝实现 4.4-利用lodash和JSON实现深 4.5-异常处理-throw和try、catch 4.6-普通函数和箭头函数的this 4.7-call方法改变this指向 4.8-apply方法 4.9-bind方法以及总结 4.10-什么是防抖以及底层实现 4.11-什么是节流以及底层实现 4.12-节流…

【教学类-50-07】20240411“数一数”图片中四种图形出现的数量随机或固定

背景需求 今天孩子们点数时&#xff0c;我核对答案&#xff0c;突然发现有两张图片上的三角、正方、椭圆、圆形只有1个&#xff0c;我感觉这个随机的概率有问题。 仔细点数后发现以下代码生成的几何图形数量是相同的 &#xff08;如果三角有3个&#xff0c;那么正方形、圆形…