Java链表OJ题

news2024/10/6 8:24:47

目录

    • 1. 删除链表中等于给定值val的所有结点
    • 2. 逆置单链表
    • 3. 链表的中间结点
    • 4. 链表中倒数第k个结点
    • 5. 将两个有序链表合并为一个新的有序链表
    • 6. 以给定值x为基准将链表分割成两部分
    • 7. 判断是否为回文链表
    • 8. 两个链表的第一个公共结点
    • 9. 判断链表中是否有环
    • 10. 链表开始入环的第一个节点

1. 删除链表中等于给定值val的所有结点

力扣203. 移除链表元素
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
在这里插入图片描述

思路:由于需要进行删除结点,在链表中删除结点,要知道该结点的前一个结点,因此定义2个结点pre和cur,pre表示cur的前一个结点。【pre和cur的关系】
在此循环过程中,一直没有判断pre的值是否等于val,所有可以在一开始就判断头结点的值是否为val,直至头的值不为val为止。
在这里插入图片描述

代码:

       while (head !=null && head.val == val) {
            head = head.next;
        }

        if (head == null) {
            return null;
        }
        ListNode pre = head;
        ListNode cur = head.next;
        while (cur != null) {
            if (cur.val != val) {
                pre = pre.next;
                cur = cur.next;
            }else {
                pre.next = cur.next;
                cur = cur.next;
            }
        }
        return head;

2. 逆置单链表

力扣206. 反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。在这里插入图片描述

思路:
①如果链表没有结点或者只有一个结点,那么不用逆置,直接返回head头结点;
②弄清楚head、cur、curNext三者之间的关系,没翻转之前head在cur的前面,那么翻转之后cur的下一个结点就是head,翻转完成之后,再给head、cur、curNex重新赋值。即cur表示正要逆置的结点,与head进行逆置,curNext表示下一个将要逆置的结点。
在这里插入图片描述
代码:

    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;
    }

3. 链表的中间结点

力扣876. 链表的中间结点
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。在这里插入图片描述

思路:快慢指针,快的每次走2步,慢的每次走1步,要考虑结点个数为奇数和偶数个的情况。s = v * t,路程等于速度乘以时间,t相同,快指针的v是慢指针的v的2倍,所以当快指针走完链表的时候,慢指针的s是快指针的一半,即为链表的中间结点。
在这里插入图片描述

代码:

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

4. 链表中倒数第k个结点

力扣 02.02. 返回倒数第 k 个节点
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。在这里插入图片描述

思路:本题不用考虑k值不合法的情况【快慢指针】
让快的指针先走k步,之后,快的走一步,慢的走一步,最后当快的为空的时候,慢指针所指的结点即为倒数第k个结点。

在这里插入图片描述

代码:

class Solution {
    public int kthToLast(ListNode head, int k) {
        ListNode slow  = head;
        ListNode fast = head;
        while (k > 0) {
            fast = fast.next;
            k--;
        }
        while (fast != null) {
            slow = slow.next;
            fast = fast.next;
        }
        return slow.val;
    }
}

5. 将两个有序链表合并为一个新的有序链表

力扣 21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
在这里插入图片描述

思路:新建一个头结点,用于拼接合并后的链表。当有一个链表走完的时候结束循环,最后直接把没走完的链表拼接在新链表的末尾就可以。
在这里插入图片描述

代码:

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode newHead = new ListNode();
        ListNode cur = newHead;
        while (list1 != null && list2 != null) {
            if (list1.val < list2.val) {
                cur.next = list1;
                cur = cur.next;
                list1 = list1.next;
            }else {
                cur.next = list2;
                cur = cur.next;
                list2 = list2.next;
            }
        }
        if (list1 != null) {
            cur.next = list1;
        }
        if (list2 != null) {
            cur.next = list2;
        }
        return newHead.next;
    }

6. 以给定值x为基准将链表分割成两部分

力扣面试题 02.04. 分割链表
给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你不需要 保留 每个分区中各节点的初始相对位置。在这里插入图片描述

思路:基准左边的链表,头结点为bb(before begin),尾结点为be(before end);基准右边的链表,头结点为ab(after begin),尾结点为ae(after end)
遍历原链表上,与基准值进行比较,如果比基准值小就放到bb和be链表上,反之放到ab和ae链表上,大体思路是最后返回bb,但还有细节需要处理。
①:前半段bb和be为空,即没有比基准小的元素,不需要进行前后拼接,那么直接返回后半段链表,即ab
②后半段ab和ae为空,不需要进行前后拼接,直接返回前半段链表,即bb
③前后都不为空,则需要将前半段尾结点be连上ab,并且后半段尾节点的指向置为空。
在这里插入图片描述

代码:

class Solution {
    public ListNode partition(ListNode head, int x) {
        if (head == null) {
            return null;
        }
        ListNode bb = null;
        ListNode be = null;
        ListNode ab = null;
        ListNode ae = null;
        while (head != null) {
            if (head.val < x) {
                if (bb == null) {
                    bb = head;
                    be = head;
                }else {
                    be.next = head;
                    be = be.next;
                }
            }else {
                if (ab == null) {
                    ab = head;
                    ae = head;
                }else {
                    ae.next = head;
                    ae = ae.next;
                }
            }
            head = head.next;
        }
        if (be == null) {
            return ab;
        }else {
            if (ae !=null) {
                be.next = ab;
                ae.next = null;
            }
            return bb;
        }
    }
}

7. 判断是否为回文链表

力扣面试题 02.06. 回文链表
编写一个函数,检查输入的链表是否是回文的。
在这里插入图片描述

思路:
①寻找链表的中间结点(快慢指针)
②将中间节点的后面链表进行逆置(3个结点之间的关系)
③前后遍历节点值是否相等
从后往前遍历的相等终止条件是head和mid相遇了(奇数个结点)或者head的下一个结点就是mid(偶数个结点)
在这里插入图片描述
代码:

class Solution {
    public boolean isPalindrome(ListNode head) {
        if (head == null) {
            return true;
        }
        //先找中间结点
        ListNode mid = finMid(head);
        //逆置后面的结点
        ListNode cur = mid.next;
        while (cur != null) {
            ListNode curNext = cur.next;
            cur.next = mid;
            mid = cur;
            cur = curNext;
        }
        while (head != null) {
            if(head.val != mid.val) {
                return false;
            }
            if (head == mid || head.next== mid) {
                return true;
            }
            head = head.next;
            mid = mid.next;
        }
        return false;
    }
    
    private ListNode finMid(ListNode head) {
        //快慢指针
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
}

8. 两个链表的第一个公共结点

力扣160. 相交链表
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
在这里插入图片描述
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
在这里插入图片描述

思路:如果2个链表有公共的结点,那么一定是“Y”型的,后面的结点元素个数一定相等,那么不同的就是前面部分,让长度长的链表先走比长度短的结点的长度差的长度,之后两个一步一步走,并且判断两个结点是否相等。
【注意】公共结点是指结点相等,不是结点值相等。
在这里插入图片描述

代码:

public class Solution {
    private int getLen(ListNode head) {
        ListNode cur = head;
        int len = 0;
        while (cur != null) {
            cur = cur.next;
            len++;
        }
        return len;
    }
    //相交结点
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int len1 = getLen(headA);
        int len2 = getLen(headB);
        ListNode p1 = headA;
        ListNode p2 =headB;
        if (len1 > len2) {
            int size = len1 - len2;
            while (size > 0) {
                p1 = p1.next;
                size--;
            }
        }else {
            int size = len2 - len1;
            while (size > 0) {
                p2 = p2.next;
                size--;
            }
        }
        while (p1 != p2) {
            p1 = p1.next;
            p2 = p2.next;
        }
        if (p1 != null) {
            return p1;
        }else {
            return null;
        }
    }
}

9. 判断链表中是否有环

力扣141. 环形链表
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路:快慢指针,快指针走2步,慢指针走1步,然后看两个指针能否再次相遇。
在这里插入图片描述

【判断环的问题实际上是数学上的“追击”问题】
思考:为什么快的走2步,慢的走1步就可以相遇呢?
答:如果快的走3步、4步等,那么可能快慢指针就无法相遇,并且有可能出现空指针异常。
快慢指针2步1步的话,可以使两者之间的距离在进入环之后,每次缩小一步,不会出现套圈的情况,快指针肯定使可以追上慢指针的。
代码:

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) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }
}

10. 链表开始入环的第一个节点

力扣142. 环形链表 II
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路:一个指针从链表起始位置开始走,一个指针从相遇点的位置开始环绕,每次都只走1步,最后两个指针会在入口点的位置相遇。
在这里插入图片描述

代码:

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) {
            slow = slow.next;
            fast = fast.next.next;
            if (fast == slow) {
                break;
            }
        }
        if (fast == null || fast.next == null) {
            return null;
        }
        fast = head;
        while (fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }
}

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

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

相关文章

【Linux】目录权限和默认权限

上期介绍了Linux的文件权限&#xff0c;这期我们仔细来说说Linux环境下目录权限和默认权限一、目录权限1.1 进入目录所需的权限我们在进入目录时需要什么样的权限呢&#xff1f;是r、w还是x呢&#xff1f;下面我们一起来验证一下&#xff1a;&#x1f4cb;如下我门拥有全部目录…

Day11 AOP介绍

1 前言AOP&#xff0c;Aspect Oriented Programming&#xff0c;面向切面编程&#xff0c;是对面向对象编程OOP的升华。OOP是纵向对一个事物的抽象&#xff0c;一个对象包括静态的属性信息&#xff0c;包括动态的方法信息等。而AOP是横向的对不同事物的抽象&#xff0c;属性与属…

【Python从入门到精通】第一阶段

文章目录前言python的起源打印hello world注释变量变量基本概念类型类型转换运算符字符串拓展字符串的三种定义方法字符串拼接字符串格式化数据输入input比较布尔类型和比较运算符if判断if elseif elif else嵌套循环while循环while循环嵌套for循环range()的使用函数的使用函数的…

3小时精通opencv(五) 利用TrackBar进行颜色检测

3小时精通opencv(五) 利用TrackBar进行颜色检测 参考视频资源:3h精通Opencv-Python 本章内容介绍如何利用TrackBar调节色域, 手动提取到我们需要的颜色 文章目录3小时精通opencv(五) 利用TrackBar进行颜色检测创建Trackbar色彩检测创建Trackbar 在opencv中使用createTrackbar函…

C语言:数组

往期文章 C语言&#xff1a;初识C语言C语言&#xff1a;分支语句和循环语句C语言&#xff1a;函数 目录往期文章前言1. 一维数组的创建和初始化1.1 数组的创建1.2 数组的初始化2. 一维数组的使用3. 一维数组在内存中的存储4. 二维数组的创建和初始化4.1 二维数组的创建4.2 二维…

大数据技术架构(组件)7——Hive:Filter PushDown Cases And Outer Join Behavior

1.2、Filter PushDown Cases And Outer Join Behavior前提:关闭优化器set hive.auto.convertjoinfalse; set hive.cbo.enablefalse;Inner Join:1、Join On中的谓词: 左表下推、右表下推2、Where谓词:左表下推、右表下推-- 第一种情况: join on 谓词 selectt1.user_id,t2.user_i…

C++函数定义和调用介绍

C函数定义和调用介绍 函数的意义&#xff1a;利用率高&#xff0c;可读性强&#xff0c;利于移植。 一个C程序中主函数有且只有一个&#xff0c;是程序的入口&#xff0c;而函数&#xff08;或称子函数&#xff09;可以有很多。 每个 C 程序都至少有一个函数&#xff0c;即主…

2021 XV6 8:locks

实验有两个任务&#xff0c;都是为了减少锁的竞争从而提高运行效率。Memory allocator一开始我们是有个双向链表用来存储空闲的内存块&#xff0c;如果很多个进程要竞争这一个链表&#xff0c;就会把效率降低很多。所以我们把链表拆成每个CPU一个&#xff0c;在申请内存的时候就…

栈和队列的应用

一、栈在括号匹配中的应用 数据结构之栈_迷茫中的小伙的博客-CSDN博客_数据结构之栈栈括号和队列的应用 二、栈在表达式求值中的应用 中缀转 ->后缀 &#xff1a; 左右先 (左边能先算,先算左边,因为这样可以保证确定性,即计算机运算的方式) 后缀转->中缀 &#xff1a…

王者荣耀入门技能树-解答

前言 前段时间写了一篇关于王者荣耀入门技能树的习题&#xff0c;今天来给大家解答一下。 职业 以下哪个不属于王者荣耀中的职业&#xff1a; 射手法师辅助亚瑟 这道题选&#xff1a;亚瑟 王者荣耀中有6大职业分类&#xff0c;分别是&#xff1a;坦克、战士、刺客、法师、…

如何好好说话-第12章 理清楚问题就是答案

生活中该不该积极主动与别人展开社交活动&#xff1f;有些时候社交活动并不开心&#xff0c;仅仅只是无聊的闲才。但他确实能拉拢人际关系&#xff0c;帮我们获得近身套路。而且有一种观点认为不善于社交的人是不成功的。注意以上说的这些都是偏见。当我们站在一个更高的维度认…

Jetpack架构组件库:Hilt

Hilt Hilt 是基于 Dagger2 的依赖注入框架&#xff0c;Google团队将其专门为Android开发打造了一种纯注解的使用方式&#xff0c;相比 Dagger2 而言使用起来更加简单。 依赖注入框架的主要作用就是控制反转&#xff08;IOC, Inversion of Control&#xff09;, 那么什么是控制…

表格相关的一些标签

<!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>表格相关的标一些签</title> </head> <body> <!-- 需求 1&#xff1a;做一个四行&#xff0c;三…

Golang进阶

"白昼会边长&#xff0c;照亮心脏,让万物生长。"一、Golang进阶我们对golang的语法进行了一定的了解后&#xff0c;也算是入门了。本节的进阶篇围绕三个方向展开,Goroutine 、 Channel 、Sync。如何理解并行与并发&#xff1f;并行是指“并排行走”或“同时实行或实施…

用数组实现链表、栈和队列

目录前言一、用数组实现链表1.1 单链表1.2 双链表二、用数组实现栈三、用数组实现队列前言 众所周知&#xff0c;链表可以用结构体和指针来实现&#xff0c;而栈和队列可以直接调用STL&#xff0c;那为什么还要费尽心思用数组来实现这三种数据结构呢&#xff1f; 首先&#x…

好的质量+数量 = 健康的创作者生态

缘起 CSDN 每天都有近万名创作者发表各种内容&#xff0c; 其中博客就有一万篇左右。 这个数量是非常可喜的&#xff0c;这也是 CSDN 的产品、研发运营小伙伴、和各位博主持续工作的结果。 衡量一个 IT 内容平台&#xff0c;除了数量之外&#xff0c;还有另外一些因素&#xf…

Linux——动态库

目录 制作并发布动态库 使用动态库 使用动态库程序运行时的错误 制作并发布动态库 静态库的代码在链接的时候会被拷贝进对应的可执行程序内部&#xff0c;动态库则不需要拷贝。 动态库在形成目标文件时&#xff0c;需要加一个选项 -fPIC&#xff1a;形成一个与位置无关的二…

Yocto常用术语

Yocto常用术语 Yocto是一套开源、专为嵌入式定制的编译系统&#xff0c;它提供了toolset和开发环境&#xff0c;开发人员可以利用Yocto定制基于Linux的系统。Yocto官网介绍了其常用术语&#xff0c;官网链接Yocto Project Terms&#xff0c;了解这些术语可以加深对Yocto的认识…

第五章 高级数据管理

在第4章&#xff0c;我们审视了R中基本的数据集处理方法&#xff0c;本章我们将关注一些高级话题。本章分为三个基本部分。在第一部分中&#xff0c;我们将快速浏览R中的多种数学、统计和字符处理函数。为了让这一部分的内容相互关联&#xff0c;我们先引入一个能够使用这些函数…

低功耗广域网LPWAN 8大关键技术对比

物联网被认为是继计算机、互联网之后&#xff0c;世界信息产业发展的第三次浪潮&#xff0c;它的出现将大大改变人们现有的生活环境和习惯。智能家居、工业数据采集等场景通常采用的是短距离通信技术&#xff0c;但对于广范围、远距离的连接&#xff0c;远距离通信技术不可或缺…