链表 OJ(一)

移除链表元素

题目连接:
https://leetcode.cn/problems/remove-linked-list-elements/description/

在这里插入图片描述

使用双指针法,开始时,一个指针指向头节点,另一个指针指向头节点的下一个结点,然后开始遍历链表删除结点。

这里要注意如果是空链表的话,使用双指针第二个指针会发生空指针异常,所以要判断一下

最后程序运行到最后,我们还差头节点没有判断,最后加上即可。

class Solution {public ListNode removeElements(ListNode head, int val) {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;}if(head.val == val) {head = head.next;}return head;}
}

反转链表

题目连接:
https://leetcode.cn/problems/reverse-linked-list/description/

在这里插入图片描述


我们还是使用双指针,不过这次有一个指针就是头指针,因为反转链表之后的头指针会发生改变,那还不如直接让头指针一起移动,先将另一个指针指向头指针的下一个结点,然后开始遍历链表,把每一个结点的指针指向的对象变为前面的对象。

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

链表的中间结点

题目链接:
https://leetcode.cn/problems/middle-of-the-linked-list/description/

在这里插入图片描述


使用快慢指针,快指针每次走两步,慢指针每次走一步,最后慢指针所指向的结点就是 中间结点

原理:fast = 2slow = 总路程

这里要注意循环的结束条件:
在这里插入图片描述当fast== null 并且 fast.next == null时,才能进入循环,并且 fast==null,要放在前面,因为只用fast不是null时才能进行 fast.next 的判断

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

返回倒数第 k 个节点

题目链接:
https://leetcode.cn/problems/kth-node-from-end-of-list-lcci/description/

在这里插入图片描述


还是使用快慢指针,先让快指针走 k-1 步,然后慢指针和快指针一起走,每次走一步,最后快指针走到最后一个结点时,慢指针所指向的节点就是倒数第 k 个节点。

原理就是让slow和fast的差值j就是k

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

合并两个有序的链表

题目链接:
https://leetcode.cn/problems/merge-two-sorted-lists/description/
在这里插入图片描述


创建一个新的头节点,list1和list2开始遍历各自的链表,然后比较,插入到新链表中,最后再看一下哪些链表没有遍历完,然后把没有遍历完的链表直接插入即可。

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

分割链表

题目链接:
https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId=8&&tqId=11004&rp=2&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

在这里插入图片描述


我们可以将单链表拆成两个链表,一个链表存储小于x 的结点,另一个链表存储大于等于x 的结点,然后将两个链表合并

这里建议使用带头链表,也就是我们常说的带哨兵位的链表,这个链表最大的好处就是可以避免头插的复杂情况,既然使用了哨兵位,就要知道最后哨兵位是要被丢弃的。

public class Partition {public ListNode partition(ListNode pHead, int x) {ListNode headA = new ListNode(-1);ListNode aLast = headA;ListNode headB =  new ListNode(-1);ListNode bLast = headB;ListNode cur = pHead;while(cur != null) {if(cur.val < x) {aLast.next = cur;aLast = aLast.next;} else {bLast.next = cur;bLast = bLast.next;}cur = cur.next;}aLast.next = headB.next;bLast.next = null;return headA.next;}
}

链表的回文结构

题目链接:
https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId=49&&tqId=29370&rp=1&ru=/activity/oj&qru=/ta/2016test/question-ranking
在这里插入图片描述


解题思路:
我们可以使用快慢指针来遍历链表找到中间结点,然后就可以把后半部分的链表进行反转,之后从这个链表头尾结点开始向中间遍历。

易错点:
1.链表的结点个数有奇数和偶数两种类型,我们需要分别讨论
2.区分奇数个结点还是偶数个结点可以从一开始找完中间结点的时候,从fast入手,因为找中间结点的循环结束就是fast最后指向尾节点还是null。
3.要一定要保存好fast的信息,因为后面在反转链表的时候fast其实已经发生了改变。

public class PalindromeList {public boolean chkPalindrome(ListNode A) {//如果是空链表返回trueif(A == null) {return true;}ListNode slow = A;ListNode fast = A;//找到中间结点while(fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;}//保存fast的结点信息,避免后面反转链表丢失信息boolean isOdd = true;//是否是奇数个结点if(fast == null) {isOdd = false;}//反转后半部分的链表ListNode prev = slow;ListNode cur = slow.next;while(cur != null) {ListNode curN = cur.next;cur.next = prev;prev = cur;cur = curN;}//前后遍历链表ListNode pA = A;ListNode last = prev;//偶数个结点if(!isOdd) {while(pA.next != last) {if(pA.val != last.val) {return false;}pA = pA.next;last = last.next;}if(pA.val != last.val) {return false;}}if (isOdd) { //奇数个结点while(pA != last) {if(pA.val != last.val) {return false;}pA = pA.next;last = last.next;}}return true;}
}

相交链表

题目链接:
https://leetcode.cn/problems/intersection-of-two-linked-lists/

在这里插入图片描述


由于是相交链表,在公共结点之前两个链表可能有一个差值,如果我们能找到这个差值,让长的链表先走差值不属,然后两个链表一起遍历,直到相遇到公共结点。

这个差值就是两个链表的长度的差。

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {int lenA = 0;int lenB = 0;ListNode cur = headA;while(cur != null) {lenA++;cur = cur.next;}cur = headB;while(cur != null) {lenB++;cur = cur.next;}int k = 0;ListNode pl = null;ListNode ps = null;if(lenA > lenB) {k = lenA - lenB;pl = headA;ps = headB;} else {k = lenB - lenA;pl = headB;ps = headA;}while(k != 0) {pl = pl.next;k--;}while(pl != ps) {pl = pl.next;ps = ps.next;}return pl;}
}

环形链表

题目链接:
https://leetcode.cn/problems/linked-list-cycle/

在这里插入图片描述


这里使用快慢指针,快指针一次走两步,慢指针一次走一步,当快指针运动到fast == null 或者 fast .next == null 这个条件时,说明链表不存在环,如果有链表存在环,那么快指针就会先进入到环中一直做圆周运动,一定会存在某一个时刻快慢指针会相遇,这时候返回true即可。

public class Solution {public boolean hasCycle(ListNode head) {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;}
}

为什么快指针每次走两步,慢指针走一步可以?

快指针会率先进入环中,然后慢指针后晚一点进入环中,由于两个指针的速度是每次差一步,也就是说两个指针每运动一次,二者之间的距离就会缩短1步,最后两个指针一定会相遇。

快指针一次走3步,走4步,…n步行吗?
快指针如果每次走三步,假设两个指针的位置如下:
在这里插入图片描述
那二者永远都不会相遇

其他情况由读者自行探讨~~

环形链表Ⅱ (找入口点)

题目链接:
https://leetcode.cn/problems/linked-list-cycle-ii/description/

在这里插入图片描述


我们还是使用快慢指针来做。

假设起点与入口点的距离为 x ,环的周长为 C ,慢指针与快指针相遇点离起点的距离为L
在这里插入图片描述
慢指针所走的路程为 x + L
快指针所走的路程为 x + L + nC (n为正整数,n = 1,2,3,4…)

这里解释一下两者的路程计算问题:
在慢指针还没有进入口点的时候,就已经至少路过一次相遇点,所以当慢指针刚刚进入环中的时候,快指针最少已经走了一圈,最多走了 n 圈。
因为慢指针刚进入环中的时候,快指针和它最多相差一个圈的距离,并且快指针的速度比慢指针的速度要快,所以慢指针是不可能走完一圈的(假设慢指针走完一圈,那快指针一定走完一圈再多一点,所以慢指针在完成一圈之前一定会被追上),所以慢指针所走的路程为 x + L,快指针所走的路程为 x + L + nC (n为正整数,n = 1,2,3,4…)中的 nC 是遇到慢指针之前就已经完成好的

当快慢指针在环中相遇时,由于快指针的速度是慢指针的速度的两倍,所以慢指针的路程是快指针的一半,即 2 * (x + L) = x + L + nC,化简整理得 x + L = nC 即 x = nC - L

推导结论:
让一个指针从头开始遍历,另一个指针从相遇点开始遍历,两个指针每次走一步,一定会在入口点相遇。

public class Solution {public ListNode detectCycle(ListNode head) {ListNode slow = head;ListNode fast = head;while(fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if(slow == fast) {break;}}//没有环if(fast == null || fast.next == null) {return null;}ListNode meet = fast;ListNode str = head;while(meet != str) {meet = meet.next;str = str.next;}return str;}
}

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

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

相关文章

泛型集合:Java中的类型安全与类型擦除

引言 泛型是Java 5引入的一项重要特性&#xff0c;它为编译时类型安全提供了支持。在集合框架中&#xff0c;泛型发挥着至关重要的作用&#xff0c;允许开发者指定集合中元素的类型&#xff0c;从而避免了类型转换的错误和运行时异常。此外&#xff0c;Java中的类型擦除机制虽然…

Spring-Data-Elasticsearch

简介 Spring Data for Elasticsearch 是 Spring Data 项目的一部分&#xff0c;该项目旨在为新数据存储提供熟悉且一致的基于 Spring 的编程模型&#xff0c;同时保留特定于存储的特性和功能。 Spring Data Elasticsearch 项目提供了与 Elasticsearch 搜索引擎的集成。Spring…

推荐一款功能强大的 GPT 学术优化开源项目GPT Academic:学术研究的智能助手

今天&#xff0c;我将向大家介绍一个强大的开源项目—GPT Academic&#xff0c;它或许正是你一直在寻找的理想工具。 已一跃成为 60.4k Star 的热门项目 GPT Academic 目前在 GitHub 上已经揽获了 60.4k 的 Star&#xff0c;这不仅反映了它的受欢迎程度&#xff0c;更证明了它…

硅纪元AI应用推荐 | 百度橙篇成新宠,能写万字长文

“硅纪元AI应用推荐”栏目&#xff0c;为您精选最新、最实用的人工智能应用&#xff0c;无论您是AI发烧友还是新手&#xff0c;都能在这里找到提升生活和工作的利器。与我们一起探索AI的无限可能&#xff0c;开启智慧新时代&#xff01; 百度橙篇&#xff0c;作为百度公司在202…

法律智能的新纪元:Transformer模型在智能法律咨询的突破性应用

法律智能的新纪元&#xff1a;Transformer模型在智能法律咨询的突破性应用 在法律领域&#xff0c;准确、高效的信息处理能力对于提供专业咨询服务至关重要。随着人工智能技术的飞速发展&#xff0c;Transformer模型凭借其卓越的语言理解能力&#xff0c;在智能法律咨询系统中…

【网络安全】Oracle:SSRF获取元数据

未经许可&#xff0c;不得转载。 文章目录 前言正文漏洞利用 前言 Acme 是一家广受欢迎的播客托管公司&#xff0c;拥有庞大的客户群体。与许多大型运营公司一样&#xff0c;Acme 采用了Apiary的服务&#xff0c;使用户能够安全高效地管理他们的播客。 Apiary 于2017年初被Or…

我的前端实习之旅

在大学的最后一年&#xff0c;我获得了一个宝贵的机会——在一家外包公司担任前端开发实习生。这一经历不仅让我得以将所学知识应用于实践&#xff0c;还教会了我许多课本之外的重要课程。 加入公司的第一天&#xff0c;我就意识到学术和职业环境之间的差异。我被分配到一个正…

PostgreSQL16安装Mac(brew)

问题 最近需要从MySQL切换到PostgreSQL。我得在本地准备一个PostgreSQL。 步骤 使用brew安装postgresql16: arch -arm64 brew install postgresql16启动postgresql16: brew services start postgresql16配置postgresql环境变量&#xff0c;打开环境变量文件&#xff1a; …

LabVIEW优化氢燃料电池

太阳能和风能的发展引入了许多新的能量储存方法。随着科技的发展&#xff0c;能源储存和需求平衡的方法也需要不断创新。智慧城市倡导放弃石化化合物&#xff0c;采用环境友好的发电和储能技术。氢气系统和储存链在绿色能源倡议中起着关键作用。然而&#xff0c;氢气密度低&…

从零开始实现大语言模型(三):Token Embedding与位置编码

1. 前言 Embedding是深度学习领域一种常用的类别特征数值化方法。在自然语言处理领域&#xff0c;Embedding用于将对自然语言文本做tokenization后得到的tokens映射成实数域上的向量。 本文介绍Embedding的基本原理&#xff0c;将训练大语言模型文本数据对应的tokens转换成Em…

JEECG框架t:datagrid表格/EasyUI框架DataGrid表格设置nowrap:false部分列不起作用或者完全不起作用

nowrap属性对于英文字母&#xff0c;数字无效&#xff0c;设置列宽度&#xff0c;也不能自动换行或者由于某些样式冲突导致直接不起作用的情况下&#xff0c;可采用以下办法解决换行问题。 解决办法&#xff1a;定义一个formatter方法&#xff0c;实现换行 /*** 表格列宽度不够…

PHP框架详解:Symfony框架

PHP框架详解&#xff1a;Symfony框架 Symfony是一个由SensioLabs创建的高性能PHP框架&#xff0c;以其模块化、灵活性和可扩展性而著称。作为PHP开发的顶级框架之一&#xff0c;Symfony在全球范围内被广泛应用于构建复杂和高性能的Web应用程序。本文将详细介绍Symfony框架的特…

【算法】排序算法介绍 附带C#和Python实现代码

1. 冒泡排序(Bubble Sort) 2. 选择排序(Selection Sort) 3. 插入排序(Insertion Sort) 4. 归并排序(Merge Sort) 5. 快速排序(Quick Sort) 排序算法是计算机科学中的一个基础而重要的部分,用于将一组数据按照一定的顺序排列。下面介绍几种常见的排序算法,…

windows USB 设备驱动开发-USB电源管理(二)

USB KMDF 功能驱动程序中的选择性挂起 如果 USB 驱动程序需要用户模式下不可用的功能或资源&#xff0c;则应提供 KMDF 函数驱动程序。 KMDF 驱动程序通过在 KMDF 初始化结构中设置相关值&#xff0c;然后提供适当的回调函数来实现选择性挂起。 KMDF 处理与较低驱动程序通信以…

无缝阅读体验:使用iCloud跨设备同步阅读进度的终极指南

无缝阅读体验&#xff1a;使用iCloud跨设备同步阅读进度的终极指南 在数字化时代&#xff0c;我们经常在多个设备上阅读电子书籍、文章和网页。无论是在通勤途中使用手机&#xff0c;在家中使用平板电脑&#xff0c;还是在工作中使用笔记本电脑&#xff0c;能够无缝地在设备之…

手撸俄罗斯方块(三)——游戏核心模块设计

手撸俄罗斯方块——游戏核心模块设计 开始游戏 按照之前的设计&#xff0c;我们需要游戏的必要元素之后即可开始游戏&#xff0c;下面以控制台上运行俄罗斯方块为例进行展开讲解。 import { ConsoleCanvas, ConsoleController, ConsoleColorTheme, Color } from shushanfx/t…

CSS技巧专栏:一日一例 3.纯CSS实现炫酷多彩按钮特效

大家好,今天是 CSS技巧专栏:一日一例 第三篇《纯CSS实现炫酷多彩按钮特效》 先看图: 开工前的准备工作 正如昨日所讲,为了案例的表现,也处于书写的习惯,在今天的案例开工前,先把昨天的准备工作重做一遍。 清除浏览器的默认样式定义页面基本颜色设定body的样式清除butt…

云视频监控中的高效视频转码策略:视频汇聚EasyCVR平台H.265自动转码H.264能力解析

随着科技的快速发展&#xff0c;视频监控技术已经广泛应用于各个领域&#xff0c;如公共安全、商业管理、教育医疗等。与此同时&#xff0c;视频转码技术作为视频处理的关键环节&#xff0c;也在不断提高视频的质量和传输效率。 一、视频监控技术的演进 视频监控技术的发展历…

SEO之网站结构优化(一)

初创企业搭建网站的朋友看1号文章&#xff1b;想学习云计算&#xff0c;怎么入门看2号文章谢谢支持&#xff1a; 1、我给不会敲代码又想搭建网站的人建议 2、新手上云 网站内的优化大致可以分为两部分&#xff0c;一是网站结构调整&#xff0c;二是页面上针对关键词的相关性优化…

前端八股文 闭包的理解

什么是闭包 闭包是指有权访问另一个函数作用域中的变量的函数 ——《JavaScript高级程序设计》 &#xff08;闭包 内层函数 引用的外层函数的变量&#xff09; 下面就是一个简单的闭包 闭包不一定必须有 return 闭包不一定有内存泄漏 闭包 什么时候用到 return 就是 外部…