详细图解LeetCode经典链表算法题

news2024/11/16 13:21:49

文章目录

  • 链表类型算法题
    • 一、链表介绍
      • 本文使用的Java中链表类:
    • 二、链表基础题
      • 1、数组转链表
        • 代码:
        • 测试:
      • 2、单链表翻转
        • 题目:
        • 代码:
        • 解析:
        • 测试:
        • 补充:
      • 3、合并两个有序链表
        • 题目:
        • 解析:
        • 代码:
        • 测试:
      • 4、两两交换链表中结点
        • 题目:
        • 解析:
        • 代码:
        • 测试:
      • 5、回文链表
        • 题目:
        • 解析:
        • 代码:
        • 测试:
    • 三、中等难度题
      • 1、合并K个升序链表
        • 题目:
        • 解析:
        • 代码:
        • 测试:
      • 2、k个一组翻转链表
        • 题目:
        • 解析:
        • 代码:
        • 测试:
      • 3、旋转链表
        • 题目:
        • 解析:
        • 代码:
        • 测试:
      • 4、环形链表
        • 题目:
        • 解析:
        • 代码:
    • 四、难题
      • 1、判断两链表是否相交,返回相交节点。
        • 图解:
        • 时间不够,我只解析了解题思路。

链表类型算法题

一、链表介绍

​ 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

本文使用的Java中链表类:

class ListNode{
    int val;
    ListNode next;
    ListNode(){};
    public ListNode(int val) {
        this.val = val;
    }
    ListNode(int val,ListNode next){
        this.val=val;
        this.next=next;
    }

    @Override
    public String toString() {
        return "ListNode{" +
                "val=" + val +
                ", next=" + next +
                '}';
    }
}

本文主要以相关算法为主,基础概念不过多赘述

二、链表基础题

1、数组转链表

是以下众多测试数据转链表的基础

代码:

//  数组给链表赋值
    public static ListNode array2LinkedList(int[] arr){
        ListNode res=new ListNode(arr[0]);
        ListNode cur=res;
        for (int i = 1; i < arr.length; i++) {
            ListNode node=new ListNode(arr[i]);
            cur.next=node;
            cur=cur.next;
        }
        return res;
    }

测试:

System.out.println(array2LinkedList(new int[]{1,2,3,4}));

image-20230127190649457

2、单链表翻转

LeetCode地址:https://leetcode.cn/problems/reverse-linked-list/

题目:

image-20230127191247017

代码:

//  单链表翻转
    public static ListNode reverseListNode(ListNode head) {
        if(head==null || head.next==null) {
            return head;
        }
        ListNode cur = reverseListNode(head.next);
        head.next.next = head;
        head.next = null;
        return cur;
    }

解析:

递归到底:

image-20230127194214825

逐步返回:

image-20230127195616916

测试:

System.out.println(reverseListNode(array2LinkedList(new int[]{1,2,3,4})));

image-20230127195854109

补充:

可以使用栈,进栈出栈可以完成逆序。

3、合并两个有序链表

LeetCode地址:https://leetcode.cn/problems/merge-two-sorted-lists/

题目:

image-20230127200421957

解析:

image-20230127201247383

代码:

//  合并两个有序链表
    public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode res = new ListNode(0);
        ListNode cur=res;
        ListNode cur1=list1;
        ListNode cur2=list2;
        while (cur1!=null||cur2!=null){
            if (cur1!=null&&cur2==null){
                cur.next=cur1;
                cur1=cur1.next;
                cur=cur.next;
                continue;
            }
            if (cur1==null){
                cur.next=cur2;
                cur2=cur2.next;
                cur=cur.next;
                continue;
            }

            if (cur1.val<=cur2.val){
                cur.next=cur1;
                cur1=cur1.next;
            }else {
                cur.next=cur2;
                cur2=cur2.next;
            }
            cur=cur.next;
        }
        return res.next;
    }

测试:

System.out.println(mergeTwoLists(array2LinkedList(new int[]{1,2,4}),array2LinkedList(new int[]{2,3,4})));

image-20230127201642970

4、两两交换链表中结点

LeetCode地址:https://leetcode.cn/problems/swap-nodes-in-pairs/

题目:

image-20230129180426240

解析:

1、

image-20230129182512317

2、

image-20230129182632159

代码:

//  两两交换链表中结点
    public static ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        ListNode next = head.next;
        head.next = swapPairs(next.next);
        next.next = head;
        return next;
    }

测试:

        int[] arr1={1,2,3,4};
        ListNode listNode1 = array2LinkedList(arr1);
        ListNode listNode = swapPairs(listNode1);
        System.out.println(listNode.toString());

image-20230129182855817

5、回文链表

LeetCode地址:https://leetcode.cn/problems/palindrome-linked-list/

题目:

image-20230129183201929

解析:

方式一:使用栈

image-20230129184831149

方式二:利用翻转链表

image-20230129194849721

代码:

方式一:使用栈

//  回文结构判断(使用栈)
    public static boolean isPalindrome(ListNode head) {
        Stack<ListNode> S=new Stack<>();
        ListNode cur=head;
        while (cur!=null){
            S.add(new ListNode(cur.val));
            cur=cur.next;
        }
        cur=head;
        while (!S.isEmpty()){
            if (S.pop().val!=cur.val) {
                return false;
            }
            cur=cur.next;
        }
        return true;
    }

方式二:利用链表翻转

//  回文结构判断不使用栈
    public static boolean isPalindrome1(ListNode head) {
        if (head==null||head.next==null) {
            return true;
        }
        ListNode curF=head;
        ListNode curL=head;
        while (curL.next!=null&&curL.next.next!=null){
            curF=curF.next;
            curL=curL.next.next;
        }
        ListNode next=curF.next;
        curF.next=null;
        ListNode node = reverseListNode(next);
        ListNode cur=node;
        curF=head;
        while (cur!=null){
            if (cur.val!= curF.val) {
                return false;
            }
            cur=cur.next;
            curF=curF.next;
        }
        return true;
    }

测试:

int[] arr1={1,2,2,1};
ListNode listNode1 = array2LinkedList(arr1);
System.out.println(isPalindrome(listNode1));
System.out.println(isPalindrome1(listNode1));

image-20230129195313654

三、中等难度题

1、合并K个升序链表

LeetCode地址:https://leetcode.cn/problems/merge-k-sorted-lists/

题目:

image-20230127202428825

解析:

其中使用合并两个有序链表的函数mergeTwoLists。

image-20230127203905372

代码:

//  合并有序链表数组
    public static ListNode mergeKLists(ListNode[] lists) {
        if (lists.length<1) {
            return null;
        }
        ArrayList<ListNode> LinkedList=new ArrayList<>();
        int i;
        for (i = 0; i < lists.length-1; i+=2) {
            ListNode listNode = mergeTwoLists(lists[i], lists[i + 1]);
            LinkedList.add(listNode);
        }
        if (i==lists.length-1){
            LinkedList.add(lists[i]);
        }
        while (LinkedList.size()>1){
            ListNode listNode = mergeTwoLists(LinkedList.get(0), LinkedList.get(1));
            LinkedList.remove(0);
            LinkedList.remove(0);
            LinkedList.add(listNode);
        }
        return LinkedList.get(0);
    }

测试:

 int[] arr={4,5};
        int[] arr1={1,2,3,4};
        int[] arr2={2,6};
        ListNode listNode0 = array2LinkedList(arr);
        ListNode listNode1 = array2LinkedList(arr1);
        ListNode listNode2 = array2LinkedList(arr2);
        ListNode[] list={listNode0,listNode1,listNode2};
        ListNode listNode = mergeKLists(list);
        System.out.println(listNode.toString());

image-20230127204246450

2、k个一组翻转链表

LeetCode地址:https://leetcode.cn/problems/reverse-nodes-in-k-group/

题目:

image-20230129201610282

解析:

使用了单链表翻转函数reverseListNode

image-20230129201455981

代码:

//  k个一组翻转链表
    public static ListNode reverseKGroup(ListNode head, int k) {
         if (k<=1) {
             return head;
         }
         ListNode cur=head;
         int a=k;
         while (a>1){
             if (cur==null||cur.next==null) {
                 return head;
             }
             cur=cur.next;
             a--;
         }
         ListNode node = reverseKGroup(cur.next, k);
         cur.next=null;
         ListNode node1 = reverseListNode(head);
         while (cur.next!=null){
             cur=cur.next;
         }
         cur.next=node;
         return node1;
    }

测试:

int[] arr1={1,2,3,4,5};
ListNode listNode1 = array2LinkedList(arr1);
System.out.println(reverseKGroup(listNode1, 2).toString());

image-20230129202033752

3、旋转链表

LeetCode地址:https://leetcode.cn/problems/rotate-list/

题目:

image-20230129205254718

解析:

image-20230129205157537

代码:

//    旋转链表正式
    public static ListNode rotateRight(ListNode head, int k) {
        if (head==null||k==0) {
            return head;
        }
        ListNode cur=head;
        //长度
        int length=0;
        while (cur.next!=null){
            cur=cur.next;
            length++;
        }
        length++;
        //计算实际位移
        k=length-k%length;
        if (k==0) {
            //整数倍无需位移
            return head;
        }
        cur.next=head;
        cur=head;
        //指针先走k步
        while (k-1>0){
            cur=cur.next;
            k--;
        }
        ListNode node=cur.next;
        cur.next=null;
        return node;
    }

测试:

int[] arr1={1,2,3,4,5};
ListNode listNode1 = array2LinkedList(arr1);
System.out.println(rotateRight(listNode1,2));

image-20230129205445639

4、环形链表

LeetCode地址:https://leetcode.cn/problems/linked-list-cycle/

题目:

(此题返回值稍作修改,有环返回如环节点,无环返回null)

image-20230129205705243

解析:

方式一:利用HashMap

image-20230129210653323

方式二:利用快慢指针

image-20230129211950713

image-20230129212009445

代码:

方式一:hashmap

//  判断链表是否有环(利用HashMap)
    public boolean hasCycle(ListNode head) {
        HashSet<ListNode> list=new LinkedHashSet<>();
        ListNode cur=head;
        while (cur!=null){
            if (list.contains(cur)) {
                return true;
            }
            list.add(cur);
            cur=cur.next;
        }
        return false;
    }

方式二:快慢指针

//  判断链表是否有环(快慢指针)有环返回入环结点
    public ListNode hasCycle2(ListNode head) {
        if (head==null||head.next==null) {
            return null;
        }
        ListNode curF=head;
        ListNode curL=head;
        while (curF.next!=null&&curF.next.next!=null){
            curF =curF.next.next;
            curL=curL.next;

            if (curF==curL){//确定有环寻找入环结点
                curF=head;//返回头结点
                while (curF!=curL){
                    curF=curF.next.next;
                    curL=curL.next;
                }
                return curF;
            }

        }
        return null;
    }

四、难题

1、判断两链表是否相交,返回相交节点。

图解:

image-20230129213102199

二、两链表中有一者为有环链表。

不存在相交

image-20230129213608914

时间不够,我只解析了解题思路。

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

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

相关文章

顺应信创发展,君子签电子签章方案全面适配信创环境

信创产业作为战略性新兴产业&#xff0c;近年来&#xff0c;国家不断出台相关政策对行业的发展进行支持。 2018年我国首次将信创纳入国家战略&#xff0c;并提出了 “28N”应用体系&#xff0c;信创发展步入“快车道”&#xff1b;2020年起&#xff0c;信创产业由党政逐渐向其…

垃圾收集器必问系列—ZGC

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 人的一切痛苦&#xff0c;本质上都是对自己的无能的愤怒。——王小波 文章目录Region布局读屏障染色指针染色指针的优势运作过程ZGC的优缺点ZGC有人称它为Zero GC&#xff0c;其实“Z”并非什么专业名词的缩写…

vue前端框架课程笔记(二)

目录计算属性问题引入插值语法实现methods配置属性实现computed配置属性一些问题getter与setter注意监视属性问题引入computed和methods实现watch属性watch属性简介computed与watch的比较注意本博客参考尚硅谷官方课程&#xff0c;详细请参考 【尚硅谷bilibili官方】 本博客以…

千峰网络安全笔记(前三讲)

典中典 《c语言从研发到脱发》 《C从入门到放弃》 《Java从跨平台到跨行业》 《Ios开发从入门到下架》 《Android开发大全——从开始到转行》 《PHP由初学至搬砖》 《黑客攻防:从入门到入狱》 《Mysql从删库到跑路》 《服务器运维管理从网络异常到硬盘全红》 《服务器运维管理…

CentOS 8 中dnf管理器如何仅下载不安装软件

在某些情况下&#xff0c;我们希望从命令行下载特定或一组 RPM 包而不安装它。虽然我们可以使用 wget 命令下载&#xff0c;但 wget 不会下载安装包的依赖项。在 CentOS 8 中DNF&#xff08;或 yum&#xff09;是一个命令行包管理工具。使用 DNF我们可以安装、更新和删除 rpm 包…

HTTP协议学习

一、http请求协议1、常见请求头accept:浏览器通过这个头告诉服务器&#xff0c;它所支持的数据类型Accept-Charset: 浏览器通过这个头告诉服务器&#xff0c;它支持哪种字符集Accept-Encoding&#xff1a;浏览器通过这个头告诉服务器&#xff0c;支持的压缩格式Accept-Language…

114.简单的动态切换app的图标

1.第一步 通过activity-alias别名实现&#xff0c;manifest 这里写的是一个默认的图标Default和一个需要切换的图标Test&#xff0c;以及一个默认的首页面HomeActivity&#xff1a; <!-- 默认的图标--> <activity-aliasandroid:name".activity.Default"and…

C语言入门教程||C语言 运算符||C语言 判断

C语言 运算符 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 语言内置了丰富的运算符&#xff0c;并提供了以下类型的运算符&#xff1a; 算术运算符关系运算符逻辑运算符位运算符赋值运算符杂项运算符 本章将逐一介绍算术运算符、关系运算符、逻辑运算符、位运算…

基于android的大学生图书管理系统app

需求信息&#xff1a; 1.学生用户端 查询图书。学生用户可以对馆内图书资料进行简单和高级的查询。 预约图书。当查询时发现要借阅的图书已被借阅&#xff0c;可以提前预约。 挂失图书。图书不慎丢失&#xff0c;可以在学生端实现挂失。 2.管理员端 学生用户管理。管理员可以对…

LeetCode——2309. 兼具大小写的最好英文字母

一、题目 给你一个由英文字母组成的字符串 s &#xff0c;请你找出并返回 s 中的最好英文字母。返回的字母必须为大写形式。如果不存在满足条件的字母&#xff0c;则返回一个空字符串。 最好 英文字母的大写和小写形式必须 都 在 s 中出现。 英文字母 b 比另一个英文字母 a …

Python 操作pdf(pdfplumber读取PDF写入Exce)

1. Python 操作pdf(pdfplumber读取PDF写入Exce) 1.1 安装pdfplumber模块库: 安装pdfplumber: pip install pdfplumber 复制代码 pdfplumber.PDF类 pdfplumber.PDF类表示单个PDF ,并具有两个主要属性: 属性说明pdf.metadata从PDF的Info中获取元数据键/值对字典。通常包括&q…

【HBase——陌陌海量存储案例】4. Apache Phoenix 介绍与安装

5. 性能问题 Hbase默认只支持对行键的索引&#xff0c;那么如果要针对其它的列来进行查询&#xff0c;就只能全表扫描之前介绍的查询是使用scan filter组合来进行查询的&#xff0c;但查询地效率不高&#xff0c;因为要进行顺序全表扫描而没有其他索引。如果数据量较大&#…

51单片机学习笔记-8 DS1302实时时钟

8 DS1302实时时钟 [toc] 注&#xff1a;笔记主要参考B站江科大自化协教学视频“51单片机入门教程-2020版 程序全程纯手打 从零开始入门”。 8.1 芯片介绍&#xff1a;DS1302 RTC(Real Time Clock)实时时钟&#xff0c;是一种集成电路&#xff0c;通常称为时钟芯片。常见的时…

AIGC在营销图片生成技术综述

基于文本生成素材imagen分析用户输入的文本并使用T5-XXL进行编码。嵌入在 AI 中的文本首先被转换为分辨率为64x64像素的小图像。Imagen进一步利用文本条件超分辨率扩散模型对图像进行6464的上采样&#xff0c;然后这个图像继续增长并最终形成。Imagen 的开发者谷歌研究的大脑团…

剑指 Offer 第11天 第12天

目录 剑指 Offer 18. 删除链表的节点 剑指 Offer 22. 链表中倒数第k个节点 剑指 Offer 25. 合并两个排序的链表 剑指 Offer 52. 两个链表的第一个公共节点 剑指 Offer 18. 删除链表的节点 给定单向链表的头指针和一个要删除的节点的值&#xff0c;定义一个函数删除该节点。…

台式电脑怎么连wifi,1分钟轻松弄懂

电脑已经成为了各位小伙伴日常生活中经常会使用的工具。笔记本电脑连接wifi很简单&#xff0c;相信很多小伙伴都会&#xff0c;可是面对台式电脑&#xff0c;很多小伙伴就不知道怎么连wifi了。台式电脑怎么连wifi&#xff1f;别担心&#xff0c;1分钟教你轻松弄懂。 台式电脑怎…

MQ消息队列

mq1、什么是消息队列1.1 MQ基本框架1.2 消息队列的优点1.3 消息队列的缺点1.4 消息队列比对2、RabbitMQ2.1、RabbitMQ如何保证消息不被重复消费2.2、RabbitMQ如何保证消息不丢失2.2.1 生产者丢数据2.2.2 消息队列丢数据2.2.3 消费者丢数据2.3、RabbitMQ如何保证消息有序2.4、Ra…

基于蜣螂算法改进的随机森林分类算法-附代码

基于蜣螂算法改进的随机森林分类算法 - 附代码 文章目录基于蜣螂算法改进的随机森林分类算法 - 附代码1.数据集2.RF模型3.基于蜣螂算法优化的RF4.测试结果5.Matlab代码摘要&#xff1a;为了提高随机森林数据的分类预测准确率&#xff0c;对随机森林中的树木个数和最小叶子点数参…

SVN关联PyCharm使用

前言 本人因为要搭建一个自动化测试的框架&#xff0c;编程语言选择的python&#xff0c;python编辑器选择的PyCharm&#xff0c;代码管理工具使用的SVN。为了方便协作开发&#xff0c;需要将SVN关联PyCharm进行使用。 一、SVN关联PyCharm 1.点击左上角File–>选择Settin…

mongodb的聚合操作

mongodb的聚合操作 学习目标 了解 mongodb的聚合原理掌握 mongdb的管道命令掌握 mongdb的表达式 1 mongodb的聚合是什么 聚合(aggregate)是基于数据处理的聚合管道&#xff0c;每个文档通过一个由多个阶段&#xff08;stage&#xff09;组成的管道&#xff0c;可以对每个阶…