List——顺序表链表OJ

news2024/11/15 7:16:58

文章目录

  • 前言
  • 一、合并两个有序链表
  • 二、使用顺序表实现“杨辉三角”
  • 三、环形链表
  • 四、环形链表Ⅱ
  • 总结


前言

上两篇内容,对链表和顺序表进行了讲解并手动实现了自己的顺序表和链表,本篇文章将结合LeetCode上的OJ题,进行具体的使用以熟悉其中的方法和使用细节。


一、合并两个有序链表

题目链接:Leetcode.21题

在这里插入图片描述

有序、链表这是题目中已经说明的,具体思路是我们创建一个新的头结点用来保存合并后的链表。分别遍历两个链表的头节点,将较小的头结点链接在新的链表后 然后头节点后移继续比较,直到一个链表为空(当有一个链表为空时,只需要将另一个链表剩余部分全部连接在答案链表之后)。

代码实现:

public class Leetcode21_MergeTwoList {
    public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode head1=list1;
        ListNode head2=list2;
        //定义一个储存答案的头结点
        ListNode ansHead= new ListNode();
        ListNode ansLast=ansHead;  //尾节点

        while (head1!=null&&head2!=null) {
        //比较两个链表头结点的大小
            if (head1.val < head2.val) {
                //先将待连接的头节点保存下来
                ListNode cur = head1;
                //链表1头节点后移
                head1 = head1.next;
                //将之前保存的头节点连接到结果链表中
                ansLast.next = cur;
                //更新结果链表的尾节点
                ansLast = cur;
            } else {
                ListNode cur = head2;
                head2 = head2.next;
                ansLast.next = cur;
                ansLast = cur;
            }
        }

            if(head1!=null){
                ansLast.next=head1;
            }else {
                ansLast.next=head2;
            }

        return ansHead.next;
    }
 }

测试代码正确性:

//测试代码正确性
    public static void main(String[] args) {
        ListNode listN1 = new ListNode(100);
        ListNode listN2 = new ListNode(200);
        ListNode listN3 = new ListNode(300);

        listN1.next = listN2;
        listN2.next = listN3;
        listN3.next=null;

        ListNode listN4 = new ListNode(100);
        ListNode listN5 = new ListNode(200);
        ListNode listN6 = new ListNode(300);

        listN4.next=listN5;
        listN5.next=listN6;
        listN6.next=null;

        ListNode ans=mergeTwoLists(listN1,listN4);

        ListNode cur=ans;
        while (cur!=null){
            System.out.print(cur.val+" ");
            cur=cur.next;
        }
  }

运行结果:

在这里插入图片描述

二、使用顺序表实现“杨辉三角”

题目链接:Leetcode.118题
在这里插入图片描述

这道题,我们需要使用List接口下的ArrayList。我们可以创建一个线性表,线性表中的每一个元素也是一个线性表,每个线性表是一个ArrayList,存储的是该行对应的元素。需要特殊处理的是三角形的前两行,第三行开始只需要首尾填1,其他使用循环结构从上一行取元素加和即可。

代码实现:

class Solution {
    public static List<List<Integer>> generate(int num) {
        List<List<Integer>> ans = new ArrayList<>();
        //零行不做任何处理  直接返回
        if (num == 0) {
            return ans;
        }
        //走到这儿,说明至少有一行,先添加一行进去
        ans.add(new ArrayList<>());
        //对第一行的顺序表添加元素1
        ans.get(0).add(1);
        //判断是不是只有一行,若是  返回
        if (num == 1) {
            return ans;
        }
        //走到这儿说明至少有两行 再添加一行(一个顺序表)进去
        ans.add(new ArrayList<>());
        //处理第二行元素
        ans.get(1).add(1);
        ans.get(1).add(1);
        //判断是否只有两行
        if (num == 2) {
            return ans;
        }
        //走到这儿  就有规律可循了  第三行之后每一行只有首尾是1,其他元素根据上一行得到
        for (int i = 3; i <= num; i++) {
        //每走一趟循环  添加一行进去
            List<Integer> cur = new ArrayList<>();
            ans.add(cur);
            ans.get(i - 1).add(1);   //这一行的首元素
            //循环体中对每一行除首尾之外的元素进行处理
            for (int j = 0; j < i - 2; j++) {
                int first = ans.get(i - 2).get(j); //获取上一行第j个元素
                int second = ans.get(i - 2).get(j + 1);//上一行第j+1个元素
                int e = first + second; //求和
                ans.get(i - 1).add(e);  //添加到这一行的顺序表中
            }
            ans.get(i - 1).add(1);  //这一行的尾元素
        }
        return ans;
    }
}

测试代码正确性:

public static void main(String[] args) throws InterruptedException {

        System.out.println(Leetcode118_Generate.generate(6));
    }

运行结果:

在这里插入图片描述

三、环形链表

题目链接:Leetcode.141题

在这里插入图片描述

思路一:哈希表,这道题比较容易想到的一个思路是,我们可以遍历这条链表,每次遍历时判断该节点是否被访问过。可以使用哈希表来存储所有已经访问过的节点。每次我们到达一个节点,如果该节点已经存在于哈希表中,则说明该链表是环形链表,否则就将该节点加入哈希表中。重复这一过程,直到我们遍历完整个链表即可。但是哈希表方法还没总结,因此我们使用一个更简单的方法。

思路二:快慢指针,此方法为Floyd判圈算法(又称龟兔赛跑算法),假想乌龟和兔子同时从同一起点在链表上移动,如果链表上没有环,那么兔子将一直处于乌龟的前方;若该链表中有环,那么「兔子」会先于「乌龟」进入环,并且一直在环内移动。等到「乌龟」进入环时,由于「兔子」的速度快,它一定会在某个时刻与乌龟相遇,即套了「乌龟」若干圈。

我们可以根据上述思路来解决本题。具体地,我们定义两个指针,一快一慢。慢指针每次只移动一步,而快指针每次移动两步。初始时,块慢指针都在位置 head,这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。否则快指针将到达链表尾部,该链表不为环形链表。

代码实现:

public boolean hasCycle(ListNode head){
		//先处理空链表和只有一个结点的情况
        if(head==null){
            return false;
        }
        if(head.next==null){
            return false;
        }
        //定义快慢指针
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null&&fast.next!=null){   //fast.next!=null  这一句很关键  没有的话会报空指针异常~
            fast=fast.next.next;  //没有fast.next!=null这个条件的话  这里会空指针异常
            slow=slow.next;
            if(fast==slow){
                return true;
            }
        }
        return false;
    }

测试代码正确性:

public static void main(String[] args) {
        ListNode listN1 = new ListNode(100);
        ListNode listN2 = new ListNode(200);
        ListNode listN3 = new ListNode(300);

        listN1.next = listN2;
        listN2.next = listN3;
        listN3.next = listN1;
        System.out.println(hasCycle(listN1));
    }

在这里插入图片描述

四、环形链表Ⅱ

题目链接:Leetcode.142题

在这里插入图片描述
与上一题不同的是,上一题只需要判断链表中有没有环,此题需要找到并返回环的入口节点,难点在于如何找到?

判断是否有环上面已经讲过了,此时找环的入口:
假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:

在这里插入图片描述
那么相遇时: slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。
因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2: (x + y) * 2 = x + y + n (y + z)

两边消掉一个(x+y): x + y = n (y + z)

因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离。

所以要求x ,将x单独放在左面:x = n (y + z) - y ,

再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z 注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针。

这个公式说明什么呢?

先拿n为1的情况来举例,意味着fast指针在环形里转了一圈之后,就遇到了 slow指针了。

当 n为1的时候,公式就化解为 x = z,

这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。

也就是在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。

让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。

那么 n如果大于1是什么情况呢,就是fast指针在环形转n圈之后才遇到 slow指针。

其实这种情况和n为1的时候 效果是一样的,一样可以通过这个方法找到 环形的入口节点,只不过,index1 指针在环里 多转了(n-1)圈,然后再遇到index2,相遇点依然是环形的入口节点。

这样我们只需要对上面的代码稍作修改,就可以AC这道题了!

代码如下:

public ListNode detectCycle(ListNode head){
        if(head==null){
            return null;
        }
        if(head.next==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){
                break;
            }
            if(fast==null||fast.next==null){
                return null;
            }
        }
        //运行到此处 说明存在环,快指针比慢指针多走了 n倍的环的长度
        //如果让指针从链表头部一直向前走并统计步数k,那么所有 走到链表入口节点时的步数 是:k=x+n(y+z)(先走 x 步到入口节点,之后每绕 1 圈环( y+z 步)都会再次到入口节点)。
        //而目前,slow 指针走过的步数为 n(y+z) 步。因此,我们只要想办法让 slow 再走 x 步停下来,就可以到环的入口。
        //但是我们不知道 x 的值,该怎么办?依然是使用双指针法。我们构建一个指针,此指针需要有以下性质:此指针和slow 一起向前走 x 步后,两者在入口节点重合。那么从哪里走到入口节点需要 x 步?答案是链表头部head
        fast=head;
        while (fast!=slow){
            slow=slow.next;
            fast=fast.next;
        }
        return slow;
    }

验证代码正确性:

public static void main(String[] args) {
		//listN1是头节点也是链表环的入口
        ListNode listN1 = new ListNode(100);
        ListNode listN2 = new ListNode(200);
        ListNode listN3 = new ListNode(300);
        listN1.next = listN2;
        listN2.next = listN3;
        listN3.next = listN1;
        System.out.println(detectCycle(listN1).val);//输出入口结点的值
    }

在这里插入图片描述


总结

本篇博客通过四道力扣题对顺序表和链表的使用以及其具体实现了ArrayList、LinkedList进行了使用,后面还会更新更多的Leetcode题~ 感兴趣的老铁店点关注不迷路 谢谢支持!

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

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

相关文章

Spring注解式缓存redis

一、Spring 整合redis 导入依赖 <redis.version>2.9.0</redis.version> <redis.spring.version>1.7.1.RELEASE</redis.spring.version><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId>&l…

Qt中操作SQLite数据库

0.前言 SQLite是一款开源、轻量级、跨平台的数据库&#xff0c;无需server&#xff0c;无需安装和管理配置。它的设计目标是嵌入式的&#xff0c;所以很适合小型应用&#xff0c;也是Qt应用开发种常用的一种数据库。 1.驱动 Qt SQL模块使用驱动程序插件&#xff08;plugins&am…

多线程与高并发(一)

【前言】&#xff1a; 多线程、JVM、操作系统。 【概述】&#xff1a; 基础概念 JUC同步工具 同步容器 Disruptor //一个MQ框架&#xff0c;公认的单机环境下效率最高。 线程池 【线程的概念】&#xff1a; 【纤程】&#xff1a; 【 run和start的区别 】&#xff1a; //n…

[附源码]Python计算机毕业设计SSM家用饰品在线销售系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【面试问题】进程和线程的区别——通俗易懂

1. ”进程“是什么1.2 管理进程1.3 内存管理1.4 进程间通信2. 线程是什么3.进程和线程的区别1. ”进程“是什么 在对比"进程"和"线程"两者之间的区别前,我们需要先了解什么是"进程"?什么是"线程"? **“进程”(process)也叫"任…

HIFI测序揭示拟南芥MSH1参与介导的细胞器基因组重组与变异积累规律

近日&#xff0c;中国农业科学院农业基因组所武志强课题组在《The Plant Journal》在线发表了题为“Long-read sequencing characterizes mitochondrial and plastid genome variants in Arabidopsis msh1 mutants”的研究论文&#xff0c;该研究通过高精度的长读长测序&#x…

安卓APP源码和设计报告——仿淘宝水果商城

项目名称 仿淘宝水果商城项目概述 随着互联网技术地高速发展&#xff0c;计算机进入到每一个人的生活里&#xff0c;从人们的生活方式到整个社会的运转都产生了巨大的变革&#xff0c;而在信息技术发达的今天&#xff0c;互联网的各种娱乐方式都在渗透到人们的生活方式之中&…

Procreate绘画教程

Procreate绘画教程 从 30 多年的设计师/插画家那里彻底有效地学习 Procreate&#xff01;已更新至 Procreate 5.2&#xff01; 课程英文名&#xff1a;Procreate Solid Foundations 此视频教程共10.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印&#xff0c;源码…

三条建议!让您在世界杯期间确保网络安全!

2022年11月&#xff0c;全球的目光都聚焦在依旧“夏日炎炎”的卡塔尔。随着人们观看、分享赛事的习惯从传统的电视转为网络&#xff0c;世界杯必将成为整个2022年的“流量王”。在我国&#xff0c;仅仅德国与日本的一场比赛在微博平台就带来了13.8亿次阅读。 据估计&#xff0…

细粒度图像分类论文研读-2020

文章目录Filtration and Distillation: Enhancing RegionAttention for Fine-Grained Visual Categorization(by localization- classification subnetwork)AbstractIntroductionApproachDiscriminative Regions ProposingFeature Learning and Recognition EnsembleFiltration…

Spring源码深度解析:十一、Spring的循环依赖

一、前言 文章目录&#xff1a;Spring源码深度解析&#xff1a;文章目录 这篇文章是接着 Spring源码深度解析&#xff1a;七、bean的加载① - doGetBean 的继续分析过程。 二、什么是循环依赖 循环依赖&#xff0c;其实就是循环引用&#xff0c;就是两个或者两个以上的 bea…

【MySQL】数据处理函数

只有当你开始相信自己时&#xff0c;你才拥有真正的人生。——《洛奇》 前言&#xff1a; 大家好&#xff0c;我是爱打拳的程序猿。今天给大家展示是数据处理函数的用法&#xff0c;分为单行处理函数和分组函数。数据处理函数主要是为了更方便解决数据的各种问题。文章以代码和…

2023年Unity UI教程

2023年Unity UI教程 Unity 新 UI 系统 UI 工具包的完整概述 课程英文名&#xff1a;Modern Unity UI with UI Toolkit 此视频教程共10.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印&#xff0c;源码附件全 下载地址 课程编号&#xff1a;336 百度网盘地址&am…

SSM框架-获取容器的方式

9 容器 9.1 获取容器 记载类路径下的容器所在的配置文件,也就是之前用的 public class App2 {public static void main(String[] args) {ApplicationContext ctx new ClassPathXmlApplicationContext("applicationContext.xml");BookDao bookDao (BookDao) ctx.…

liunx 部署 kkfileview文件预览 以及解决https访问

kkfileview gitee地址 https://gitee.com/kekingcn/file-online-preview 1.下载office组件 wget https://kkfileview.keking.cn/LibreOffice_7.1.4_Linux_x86-64_rpm.tar.gz tar -zxvf LibreOffice_7.1.4_Linux_x86-64_rpm.tar.gz cd LibreOffice_7.1.4.2_Linux_x86-64_rpm/R…

TensorRT推理手写数字分类(一)

系列文章目录 &#xff08;一&#xff09;使用pytorch搭建模型并训练 文章目录系列文章目录前言一、网络搭建1.LeNet网络结构2.pytorch代码二、网络训练1.pytorch代码2.结果展示三、保存和加载模型1.保存整个网络2.保存网络中的参数总结前言 为了学习一下使用TensorRT进行推理…

硬核!Github星标79.4K的阿里强推Java面试参考指南到底有多强?

谈到Java面试&#xff0c;相信大家第一时间脑子里想到的词肯定是金三银四&#xff0c;金九银十。好像大家的潜意识里做Java开发的都得在这个时候才能出去面试&#xff0c;跳槽成功率才高&#xff01;但LZ不这么认为&#xff0c;LZ觉得我们做技术的一生中会遇到很多大大小小的面…

Java并发编程—如何写好代码?链式调用该怎么玩?

目录 一、案例说明 二、原生方式代码流程 三、链式调用代码流程 四、链式调用手搓的方式&#xff1a; 五、总结&#xff1a; 在上一篇博客https://blog.csdn.net/qq_52545155/article/details/128212148?spm1001.2014.3001.5501&#xff0c;博主在写商城统计商品价格的时…

mybatis中其他数据源也使用XML进行操作(SqlSessionFactory.openSession(Connection connection)方法)

文章目录1. 前言2. 先说结论3. 例子1. 准备数据2. 思考过程3. 结论1. 前言 当前在使用springbootmybatis的时候&#xff0c;通常会先在配置文件中配置好数据源&#xff0c;并在Mapper.xml文件编写好相关SQL&#xff0c;使用mybatis进行对数据库进行所谓的crud操作。 有时候会出…

nginx代理https妈妈级手册

目录 背景说明 相关地址 https证书生成 nginx安装及配置 结果展示​编辑 背景说明 为了保证传输加密、访问安全&#xff0c;我们采用nginx服务器将http服务代理为https。所需材料&#xff1a;openssl&#xff08;用来生成证书&#xff09;、http服务、nginx自身。 相关地址…