Java数据结构-链表OJ题

news2024/11/26 18:35:58

目录

  • 1. 移除链表元素
  • 2. 反转链表
  • 3. 返回中间结点
  • 4. 返回倒数第k个结点
  • 5. 合并两个有序链表
  • 6. 分割链表
  • 7. 回文链表
  • 8. 找相交链表的公共结点
  • 9. 判断链表是否有环
  • 10. 返回链表环的入口

老铁们好,学习完链表这个数据结构之后,怎么能少了OJ题呢?!今天它来了!

1. 移除链表元素

在这里插入图片描述
题目链接:移除链表元素
题目要求:

删除链表中所有值为val的结点

解题思路: 拿题目的实例1举例,链表可能出现:前面的结点的值全是6的情况,也可能整个链表的结点值都是6(如图)。所以删除前,先处理掉前面部分
在这里插入图片描述
怎么处理嘞?很简单,让头结点head一直往后走就行了,如果head为空了就返回
情况1
情况1
情况2
情况2
处理完前面部分就可以开始删除了,因为处理了前面部分,所以此时head的值一定不是val,所以初始状态,定义cur指向链表的第二个结点,prev指向第一个结点,cur用于遍历链表,prev则保存了cur的前一个结点的位置,当cur结点的值为val时,让prev的next指向cur的next即可,如图:
在这里插入图片描述
代码:

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        if (head == null) {
            return null;
        }
        // 处理前面部分
        while (head.val == val) {
            head = head.next;
            if (head == null) {
                return head;
            }
        }
        ListNode prev = head;
        ListNode cur = head.next;
        while (cur != null) {
            if (cur.val == val) {
                prev.next = cur.next;
            } else {
                prev = cur;
            }
            cur = cur.next;
        }
        return head;
    }
}

2. 反转链表

在这里插入图片描述

题目链接:反转链表
题目要求:
将原来的链表反转,返回新链表的头结点
解题思路:
如图(注意箭头的方向!):遍历链表,每遍历一个结点就让当前的结点的next指向前一个结点(头插法),接着更新head。遍历前,不要忘了把第一个结点的next置空,因为反转后第一个结点变成最后一个结点,最后一个结点的next值应该是null!!!
在这里插入图片描述

代码:

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

3. 返回中间结点

在这里插入图片描述

题目链接:链表的中间结点
题目要求:
返回链表的中间结点,如果中间结点有两个,返回第二个结点
解题思路: 快慢指针,定义一个fast指针和slow指针,fast和slow的起点相同,都是指向第一个结点,每次让fast向后移动两步,slow向后移动一步,当fast指向最后一个结点时,slow指向的刚好是中间结点
原理: 让两个人在同一起跑点开始跑步(直线运动),一个人的速度是另一个人的两倍,时间相同的情况下,速度快的人跑完全程,速度慢的人的路程刚好是全程的一半
中间结点只有一个的情况:
在这里插入图片描述
中间结点有两个的情况:
在这里插入图片描述

代码:

class Solution {
    public ListNode middleNode(ListNode head) {
        if(head == null) {
            return null;
        }
        ListNode fast = head;
        ListNode slow = head;
        while(fast!=null&&fast.next!=null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
}

4. 返回倒数第k个结点

在这里插入图片描述

题目链接:返回倒数第k个结点
题目要求: 返回倒数第k个结点的val值,给定的k保证是有效的
解题思路:
快慢指针,让快的指针先走完倒数第k个与最后一个结点的差值(走k-1步),然后快慢指针一起走

在这里插入图片描述

代码:

class Solution {
    public int kthToLast(ListNode head, int k) {
        ListNode fast = head;
        ListNode slow = head;
        //快指针先走k-1步
        for(int i =0;i<k-1;i++) {
            fast = fast.next;
        }
        //一起走
        while(fast.next!=null) {
            //
            fast = fast.next;
            slow = slow.next;
        }
        return slow.val;
    }
}

5. 合并两个有序链表

在这里插入图片描述

题目链接:合并两个有序链表
题目要求: 将两个升序的链表合并为一个升序的链表
解题思路: 定义新的结点newHead,表示新链表的头结点,再定义newTail表示新链表的尾结点,定义l1、l2用于遍历原来的两个链表,比较l1、l2结点的值,将小的值的结点给新的链表,重复这个操作,如果l1遍历结束,newTail的next=l2,如果l2遍历结束,newTail的next=l1
在这里插入图片描述

代码:

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode l1 = list1;
        ListNode l2 = list2;
        if(l1==null) {
            return l2;
        }
        if(l2==null) {
            return l1;
        }
        ListNode newHead = null;
        ListNode newTail = null;
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                //
                if (newTail == null) {
                    newHead = newTail = l1;
                    l1 = l1.next;
                } else {
                    newTail.next = l1;
                    newTail = l1;
                    l1 = l1.next;
                }
                
            } else {
                if (newTail == null) {
                    newHead = newTail = l2;
                    l2 = l2.next;
                } else {
                    newTail.next = l2;
                    newTail = l2;
                    l2 = l2.next;
                }                
            }
        }
        //
        if(l1==null) {
            newTail.next = l2;
        }else {
            newTail.next = l1;
        }
        return newHead;
    }
}

6. 分割链表

在这里插入图片描述

题目链接:链表分割
题目要求:
如图,小于x的结点在前,大于等于x的结点在后,不改变原来的顺序意思是:5在4之前,操作之后5还在4之前
在这里插入图片描述
解题思路:
定义LeftHead(左边部分的头结点)和LeftTail(左边部分的尾结点),维护左边部分(小于x的结点);定义RightHead(右边部分的头结点)和RightTail(右边部分的尾结点),维护右边部分(大于等于x的结点);将小于x的结点尾插到左边部分,将大于等于x的结点尾插到右边部分,接着将左右两边连接即可

注意事项:
可能会出现链表中所有的结点都小于x或者都大于等于x,如果都小于x,直接返回左边部分;如果都大于等于x,直接返回右边部分

代码:

public ListNode partition(ListNode pHead, int x) {
        // write code here
        if (pHead == null) {
            return null;
        }
        ListNode cur = pHead;
        ListNode LeftHead = null;//左边部分的头
        ListNode LeftTail = null;//左边部分的尾
        ListNode RightHead = null;//右边部分的头
        ListNode RightTail = null;//右边部分的尾
        while (cur != null) {
            if (cur.val < x) {
                if (LeftHead == null) {
                    //第一次插
                    LeftHead = LeftTail = cur;
                } else {
                    LeftTail.next = cur;
                    LeftTail = LeftTail.next;
                }
                cur = cur.next;
            } else {
                if (RightHead == null) {
                    //第一次插
                    RightHead = RightTail = cur;
                } else {
                    RightTail.next = cur;
                    RightTail = RightTail.next;
                }
                cur = cur.next;
            }
        }
        if (LeftHead == null) {
            return RightHead;
        }
        LeftTail.next = RightHead;
        if (RightHead != null) {
            RightTail.next = null;
        }
        return LeftHead;
    }

7. 回文链表

在这里插入图片描述

题目链接:回文链表
题目要求: 判断链表是否为回文链表,回文指的是从前往后看和从后往前看是一样的,如1234321是回文,121是回文,12不是回文
解题思路: 找到中间结点,然后将后半部分反转,接着定义两个临时结点,一个指向头,另一个指向后半部分,依次两两比较判断结点的val值是否相等。首先,找到中间结点,前面我们实现过了,反转结点我们也实现过了,所以这个题一下就变简单了
代码:

class Solution {
    public boolean isPalindrome(ListNode head) {
        if (head == null) {
            return false;
        }
        ListNode fast = head;
        ListNode slow = head;
        //
        while (fast != null&&fast.next!=null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode Newhead =  reverseList(slow);
        ListNode tmp1 = head;
        ListNode tmp2 = Newhead;
        while(tmp2!=null) {
            //
            if(tmp2.val!=tmp1.val) {
                return false;
            } else {
                tmp1= tmp1.next;
                tmp2= tmp2.next;
            }
        }
        return true;
    }

    //翻转链表
    public ListNode reverseList(ListNode head) {
        if (head == 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;
    }
}

8. 找相交链表的公共结点

在这里插入图片描述

题目链接:相交链表
题目要求: 返回两个链表相交的结点,如果不相交,返回null
解题思路: 分别计算两个链表的长度,定义两个临时结点分别指向两个链表的头,让长度长的链表临时结点往后走长度的差值步,接着两个临时结点一起走
在这里插入图片描述

代码:

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA==null||headB==null) {
            return null;
        }
        int countA = 0;//记录A的长度
        int countB = 0;//记录B的长度
        ListNode curA = headA;
        ListNode curB = headB;
        while(curA!=null) {
            countA++;
            curA = curA.next;
        }
        while(curB!=null) {
            countB++;
            curB = curB.next;
        }
        if(countA>countB) {
            //A链表更长
            for(int i=0;i<countA-countB;i++) {
                headA = headA.next;
            }
        }
        if(countA<countB) {
            //B链表更长
            for(int i=0;i<countB-countA;i++) {
                headB = headB.next;
            }
        }
        //让临时结点回去
        curA = headA;
        curB = headB;
        //一起走
        while(curA!=null) {
            if(curA==curB) {
                return curA;
            }
            curA = curA.next;
            curB = curB.next;
        }
        return curB;
    }
}

9. 判断链表是否有环

在这里插入图片描述
题目链接:环形链表
题目要求: 判断链表是否存在环如果存在环返回true,否则返回false,
解题思路: 还是快慢指针,想象一下:你和你对象在你的宿舍楼下,你们一起往操场跑(环形操场),你们两个的速度肯定有快有慢,不可能完全一样,你们跑呀跑,肯定会在操场中相遇。链表也是如此,这里我们让fast的速度为slow的两倍,fast每次走两步,slow每次走一步
代码:

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null) {
            return false;
        }
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next!=null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                return true;
            }
        }
        return false;
    }
}

10. 返回链表环的入口

在这里插入图片描述

题目链接:环形链表Ⅱ
题目要求: 如果链表存在环,返回环的入口,如果不存在环返回null
解题思路: 如图:
在这里插入图片描述

代码:

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                // 两人相遇,说明链表成环
                while (head != slow) {
                    slow = slow.next;
                    head = head.next;
                }
                return head;
            }
        }
        return null;
    }
}

今天的内容就到这里,感谢老铁们的点赞、收藏、评论~❤

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

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

相关文章

下载及安装PHP,composer,phpstudy,thinkPHP6.0框架

文章目录 目录 文章目录 前言 一、下载PHP 二、下载composer 三、下载PHPstudy 四、下载think PHP 1.下载 2.多应用开发 前言 thinkPHP是一款开源的PHP框架&#xff0c;它是基于MVC&#xff08;Model-View-Controller&#xff09;设计模式构建的。thinkPHP提供了丰富的…

牛客NC30 缺失的第一个正整数【simple map Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/50ec6a5b0e4e45348544348278cdcee5 核心 Map参考答案Java import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可…

【跟着CHATGPT学习硬件外设 | 01】SPI

文章目录 &#x1f680; 概念揭秘关键精华&#x1f31f; 秒懂案例生活类比实战演练 &#x1f50d; 原理与工作流程探秘步骤1&#xff1a;初始化SPI接口步骤2&#xff1a;主设备启动通信步骤3&#xff1a;主设备发送数据步骤4&#xff1a;从设备接收数据步骤5&#xff1a;从设备…

Android开发 OCR:通过Tesseract实现图片文字识别

下面是整个详解步骤过程 效果图一、OCR的含义二、什么是Tesseract三、前提准备1、添加依赖2、数据文件下载路径 四、实际代码案例Demo如下&#xff1a;Main.xmlMain.java 效果图 流程&#xff1a;获取assets中的图片显示到页面&#xff0c;提取照片内的文字 一、OCR的含义 o…

输出1到10的阶乘--C语言

#include<stdio.h> int fac(int n){if(n<1){return 1;}elsereturn fac(n-1)*n; } int main(){int i, result;for(i1;i<10;i){resultfac(i);printf("%d!%d\n",i,result);}} 输出结果&#xff1a;

软件工程 - 04 需求分析

文章目录 需求分析需求分析方法系统建模用例图类图对象图活动图时序图协作图构件图部署图 软件开发各个阶段的图 需求分析 软件开发中非常重要的一环&#xff1b;好的需求分析方法&#xff0c;可以帮助更好地理解用户需求&#xff0c;准确定义系统的功能和性能要求&#xff0c…

特征选择集大成的包-arfs(python)

特征选择集大成的包-arfs&#xff08;python&#xff09; 一、介绍 arfs介绍文档https://arfs.readthedocs.io/en/latest/Introduction.html 英文好的朋友可以阅读作者写的介绍&#xff1a; All relevant feature selection means trying to find all features carrying info…

kubernetes(K8S)学习(七):K8S之系统核心组件

K8S之系统核心组件 K8s系统核心组件1.1 Master和Node1.2 kubeadm1.3 先把核心组件总体过一遍1.4 Kubernetes源码查看方式1.5 kubectl1.6 API Server1.7 集群安全机制之API Server1.8 Scheduler1.9 kubelet1.10 kube-proxy K8s系统核心组件 1.1 Master和Node 官网 &#xff1a;…

Java学习笔记(23)

多线程 并发 并行 多线程实现方式 1.继承Thread类 自己创建一个类extends thread类 Start方法开启线程&#xff0c;自动执行重写之后的run方法 2.实现runable接口 自己创建一个类implements runnable Myrun不能直接使用getname方法&#xff0c;因为这个方法是thread类的方法…

小迪学习笔记(内网安全)(常见概念和信息收集)

小迪学习笔记&#xff08;内网安全&#xff09;&#xff08;一&#xff09; 内网分布图内网基本概念工作组和域环境的优缺点内网常用命令域的分类单域父域和子域域数和域森林 Linux域渗透问题内网安全流程小迪演示环境信息收集mimikatzLazagne(all)凭据信息政集操作演示探针主机…

2536. 子矩阵元素加 1

跳转题目 本题暴力可以做&#xff0c;猜到用差分&#xff0c;但是不熟&#xff0c;不知道二维差分怎么用&#xff0c;碰到用差分的题目太少了。 暴力算法&#xff1a; class Solution { public:vector<vector<int>> rangeAddQueries(int n, vector<vector<…

nuxt学习

一、遇到的问题 1、nuxt初始化失败问题解决方案 使用npm和pnpm初始化都失败 原因&#xff1a;主机连不上DNS服务器 解决方案 Step1: 打开文件夹 Windows:路径&#xff1a;C:\Windows\System32\drivers\etc Mac: 路径&#xff1a;/etc/hosts Step2: 使用记事本方式打开 …

如何在Linux系统部署ONLYOFFICE协作办公利器并实现多人实时编辑文档

文章目录 1. 安装Docker2. 本地安装部署ONLYOFFICE3. 安装cpolar内网穿透4. 固定OnlyOffice公网地址 本篇文章讲解如何使用Docker在本地服务器上安装ONLYOFFICE&#xff0c;并结合cpolar内网穿透实现公网访问。 Community Edition允许您在本地服务器上安装ONLYOFFICE文档&…

五、Elasticsearch 集成

目录 5.1 Spring Data 框架集成5.1.1 Spring Data 框架介绍5.1.2 Spring Data Elasticsearch 介绍5.1.3 Spring Data Elasticsearch 版本对比5.1.4 集成步骤 5.1 Spring Data 框架集成 5.1.1 Spring Data 框架介绍 Spring Data 是一个用于简化数据库开发的开源框架。其主要目…

ctfshow xxe web373-378

web373 libxml_disable_entity_loader(false)&#xff1a;这行代码用于启用实体加载器&#xff0c;允许加载外部实体。 $xmlfile file_get_contents(php://input)&#xff1a;从输入流中读取XML数据并存储在 $xmlfile 变量中。 $dom->loadXML($xmlfile, LIBXML_NOENT |…

从零开始机器学习(机器学习 监督学习之线性回归 损失函数及可视化 梯度下降 线性回归的平方误差损失函数 lab实验)

文章目录 机器学习定义监督学习之线性回归损失函数及可视化梯度下降线性回归的平方误差损失函数lab实验 机器学习定义 机器学习就是机器通过不断训练数据集从逐渐知道正确的结果 机器学习包括监督学习和非监督学习 监督学习&#xff1a;需要输入数据和结果数据来不断训练学习…

晚间兼职新选择:6种副业让你收入满意

晚上&#xff0c;是许多人放松身心、享受闲暇时光的时刻&#xff0c;但你知道吗&#xff1f;它也是开启副业之门的黄金时段。接下来&#xff0c;我将为你揭晓6个特别适合晚间操作的副业&#xff0c;期待能助你一臂之力。 1,网络兼职新篇章&#xff1a;在浩瀚的互联网海洋中&am…

2024年北京通信展|北京国际信息通信展览会|北京PT展

2024年北京通信展|北京国际信息通信展览会|北京PT展 2024年中国国际信息通信展览会&#xff08;PTEXPO&#xff09;&#xff0c;是由工业和信息化部主办的ICT行业盛会&#xff0c;自1990年创办以来&#xff0c;已成功举办31届&#xff0c;是反映信息通信行业发展最新成果的重要…

NO13 蓝桥杯单片机之NE555的使用及实践

由于LM555的内容较少&#xff0c;因此就把使用方法和代码实践放在一起了。 1 NE555使用方法 NE555是一个“信号发生电路”&#xff0c;可以理解为一个“方波产生器”&#xff0c;值得注意的是&#xff0c;其是一个硬件电路&#xff0c;一旦确定了功能也就确定了&#xff0c;所…

JDK,JRE,JVM 区别和联系【大白话Java面试题】

JDK&#xff0c;JRE&#xff0c;JVM 区别和联系 大白话回答&#xff1a; JDK是开发环境一般开发人员需要&#xff0c;包含开发环境&#xff08;JDK)和运行环境&#xff08;JRE&#xff09;&#xff0c;JRE是运行环境&#xff0c;普通用户需要。jre文件夹下的bin文件夹就是JVM的…