【牛客网刷题记录】【java】链表

(1)反转链表

链接
可以说是最经典的链表题目之一,并且很多人经常会记不得怎么做。
但大致思路是比较简单的,重点就是如何用指针对链表进行反转的同时还不能丢失链表。不可避免的就是需要一个指针指向已经反转的部分(pre),另一个是指向仍未反转的部分(cur)。
例如节点是A->B->C, pre指向A,cur指向B,每次用cur向后移动(C),代表待反转的变少,pre要移动到B,并且将B的next指向A,这就需要多一个tmp指针。

JAVA:

public class Solution {public ListNode ReverseList (ListNode head) {ListNode pre=null, cur=head, tmp=null;while(cur!=null){tmp=cur;cur=cur.next;tmp.next=pre;pre=tmp;}return tmp;}
}

(2)链表内指定区间反转

链接

最简单的方法就是,将需要反转的部分提出,反转后再放回去。

public class Solution {/*** * @param head ListNode类 * @param m int整型 * @param n int整型 * @return ListNode类*///说明:方便理解,以下注释中将用left,right分别代替m,n节点 public ListNode reverseBetween (ListNode head, int m, int n) {//设置虚拟头节点ListNode dummyNode = new ListNode(-1);dummyNode.next = head;ListNode pre = dummyNode;//1.走left-1步到left的前一个节点for(int i=0;i<m-1;i++){pre = pre.next;}//2.走roght-left+1步到right节点ListNode rigthNode = pre;for(int i=0;i<n-m+1;i++){rigthNode = rigthNode.next;}//3.截取出一个子链表ListNode leftNode = pre.next;ListNode cur = rigthNode.next;//4.切断链接pre.next=null;rigthNode.next=null;//5.反转局部链表reverseLinkedList(leftNode);//6.接回原来的链表pre.next = rigthNode;leftNode.next = cur;return dummyNode.next;}//反转局部链表private void reverseLinkedList(ListNode head){ListNode pre = null;ListNode cur = head;while(cur!=null){//Cur_next 指向cur节点的下一个节点ListNode Cur_next = cur.next;cur.next = pre;pre = cur;cur = Cur_next ;}}
}

(3)合并两个排序的列表

链接
说实话,这题我认为递归是最清晰且好理解的。
两个链表的元素怎么衔接节点大致有如下考虑:例如有a和b节点,a小于b并不能说明a后面要衔接b,因为a的后一个值可能大于b。因此要判断到a小于b且a后的值大于b。同时,如果出现了一个链表已经遍历完后,可以直接加在后面(类似于归并排序)。
但这样的问题就是代码会比较冗余,因为需要判断现在谁是更小的节点。如果用递归,则可以很自然的处理那个节点的值更小的情况。我们每次判断当前的a和b节点谁更小,将小的值的下一个节点和大的节点放入递归即可。

public ListNode Merge (ListNode pHead1, ListNode pHead2) {// 特判为空if(pHead1==null || pHead2==null){return pHead1==null? pHead2 : pHead1;}if(pHead1.val<=pHead2.val){pHead1.next=Merge(pHead1.next, pHead2);return pHead1;}else{pHead2.next=Merge(pHead1, pHead2.next);return pHead2;}}

或者使用迭代来写,也比较简单。创建一个dummy节点,将剩余的节点续在dummy后面:

 public ListNode Merge (ListNode pHead1, ListNode pHead2) {// 特判为空if (pHead1 == null || pHead2 == null) {return pHead1 == null ? pHead2 : pHead1;}ListNode dummy = new ListNode(0);ListNode p1 = pHead1, p2 = pHead2, tmp=dummy;while(p1!=null&&p2!=null){if(p1.val<p2.val){tmp.next=p1;p1=p1.next;}else{tmp.next=p2;p2=p2.next;}tmp=tmp.next;}tmp.next = (p1 == null) ? p2 : p1;return dummy.next;}

(4)合并k个已排序的链表

链接
最开始的思路就像是做归并(多路归并,常用于磁盘),用一个tmpList存储lists里的子链表的头指针,然后再每次选出最小的指针,将该指针指向的内容挂到dummy的后面。这样的思路很类似与归并排序。
在这里插入图片描述
而这样的操作可以进一步简化,不需要加入tmplist:这是因为表面上看lists是一个arraylist,每个元素是一串链表,但实际上每个元素存储的还是指针,而后续的链表节点都是由指针连接起来的。因此lists和我们设想的tmplist其实是一样的。
我们要做的是:每次从list的子链表选一个最小的,用minNode这个指针进行表示。添加到res后,minNode向后移动。这里的set方法是更新 lists 中对应链表的当前节点。

public ListNode mergeKLists(ArrayList<ListNode> lists) {if (lists == null || lists.size() == 0) {return null;}ListNode dummy = new ListNode(0);ListNode res = dummy;int len = lists.size();while (true) {ListNode minNode = null;int minFlag = -1;// 找到当前最小节点for (int i = 0; i < len; i++) {ListNode node = lists.get(i);if (node != null && (minNode == null || node.val < minNode.val)) {minNode = node;minFlag = i;}}// 如果所有链表都遍历完了,跳出循环if (minNode == null) {break;}// 将最小节点添加到结果链表中res.next = minNode;res = res.next;// 更新对应链表的当前节点lists.set(minFlag, minNode.next);}return dummy.next;
}

顺便说一下:

lists.get(minFlag)=lists.get(minFlag).next;

这样的操作是不合法的。代码本意是想表达将minFlag位置的内容(即指针)指向下一个元素,但是在Java中,方法调用的结果是一个值,而不是一个可以赋值的左值,即lists.get(minFlag) 是一个方法调用的结果,它返回一个 ListNode 对象的引用,但这个引用本身不是一个可以赋值的变量。
为了更新 ArrayList 中的元素,你需要使用 ArrayList 的 set 方法。set 方法允许你指定索引并更新该索引处的元素。例如:

lists.set(minFlag, lists.get(minFlag).next);

上面的代码可以完成要求,但每次需要找到子列表的最小值,这就增加了操作,提高了时间复杂度。我们可以考虑用最小堆(优先队列)来优化:

public ListNode mergeKLists(ArrayList<ListNode> lists) {if (lists == null || lists.size() == 0) {return null;}ListNode dummy = new ListNode(0);ListNode res = dummy;// 使用优先队列(最小堆)来优化查找最小节点的过程PriorityQueue<ListNode> pq = new PriorityQueue<>((a, b) -> a.val - b.val);//(a, b) -> a.val - b.val:这是一个Lambda表达式,用于定义比较器。// 初始化优先队列for (ListNode node : lists) {if (node != null) {pq.add(node);}}while (!pq.isEmpty()) {ListNode minNode = pq.poll();res.next = minNode;res = res.next;if (minNode.next != null) {pq.add(minNode.next);}}return dummy.next;}

对于lambda表达式:在Java中,Comparator 接口用于定义对象的比较规则。PriorityQueue 使用这个比较器来确定元素的顺序。比较器的 compare 方法通常返回一个整数值,用于表示两个对象的相对顺序:

负值:表示第一个对象小于第二个对象。
零:表示两个对象相等。
正值:表示第一个对象大于第二个对象。

(5) 判断链表中是否有环

链接
很经典的题目,用快慢指针可以很快的得到是否成环。如果成环,快指针肯定会追上慢指针。

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

(6) 链表中环的入口结点

链接
上面的题目的进阶,这次还要判断入口在哪里。因为双指针相遇的地方不会是入口,因此直接返回slow是不对的。这里需要一些数学推理:
在这里插入图片描述
这里设slow和fast走的距离是Lslow和Lfast,环之前的长度为a,环长度为b,换入口到相遇地点长度为x。那么则有:

  • Ls=a+x
  • Lf=2a+2x=a+b+x
    可以得到a=b-x,也就是新的指针(ptr)从头开始走到入口和slow继续走到入口的距离一样,因此第二个循环则是针对这两个指针。
public ListNode EntryNodeOfLoop(ListNode pHead) {ListNode slow=pHead, fast=pHead, ptr=pHead;boolean flag=false;while(fast!=null && fast.next!=null){slow=slow.next;fast=fast.next.next;if(slow==fast){flag=true;break;}}// 判断是否有环,如果没有环,则返回nullif(flag==false){return null;}while(true){if(slow==ptr){break;}slow=slow.next;ptr=ptr.next;}return slow;}

(7)链表中倒数最后k个结点

链接
也算快指针的做法,先让快指针走k个(有dummy节点),之后再让slow和fast同时走,即可找到倒数的节点。注意输入样例会有超出链表长度的输入,加入判断语句即可。

public ListNode FindKthToTail (ListNode pHead, int k) {// write code hereListNode dummy=new ListNode(-1);dummy.next=pHead;ListNode fast=dummy, res=pHead;for(int i=0; i<k; i++){fast=fast.next;if(fast==null){return null;}}while(fast.next!=null){fast=fast.next;res=res.next;}return res;}

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

链接
在这里插入图片描述
也是数学推理,假设第一个链表到交点之前的长度为a,第二个链表到交点之前的长度为b,公共长度为x。因此如果指针遍历完自己的链表,再跳转到另一个链表遍历,那么两个指针一定会在交点相遇。

  • a+x+b=b+x+a
    这样可以得到代码:
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {ListNode ptr1=pHead1, ptr2=pHead2;while(ptr1!=ptr2){ptr1 = (ptr1 != null) ? ptr1.next : pHead2;ptr2 = (ptr2 != null) ? ptr2.next : pHead1;}return ptr1;}

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

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

相关文章

2024个人简历模板免费可编辑,可能是整理最全的简历(支持Word格式下载)

提供各行业简历模板WORD可编辑格式下载&#xff0c;涵盖求职简历模板、大学生简历模板、个人简历模板、留学简历模板、英文简历模板、免费简历模板、工作简历模板、保研简历模板、暑期实习简历、寒假实习简历、校招简历等。 都是word格式&#xff0c;直接下载就能用。 网盘链…

【CNKI/CPCI检索,本周召开】2024现代教育、人文与艺术国际会议(MEHA2024)

会议日期&#xff1a;2024年9月27-29日 会议地点&#xff1a;中国-郑州市 【主办单位】 国际应用科学与技术协会(IAAST) 【主讲嘉宾】 【论文出版与检索】 一、大会将围绕会议主题进行论文征集与遴选&#xff0c;所有投稿都必须经过2-3位组委会专家审稿。所有录用论文将发表…

无法访问zenodo.org解决方案-window系统

1.zenodo功能 科研数据库Zenodo&#xff1a;用于存储和分享科学研究成果&#xff1a;用户可以将科研论文、数据集、软件代码、预印本、技术报告等各种科研成果上传至Zenodo平台&#xff0c;进行存储和分享。 2.查询zenodo.org的ip地址 用站长之家网站&#xff1a;http://ip.…

【已解决】键盘输入数字-使用JAVA语言实现键盘输入的数字再通过快速排序算法输出

文章目录 一、前言任务描述相关知识分治策略&#xff1a;编程要求测试说明 二、具体代码实现总结 一、前言 —快速排序 任务描述 在待排序的n个元素中任取一个元素&#xff08;通常取第一个元素&#xff09;作为基准&#xff0c;把该元素放入最终位置后&#xff0c;整个数据序…

C++(学习)2024.9.23

目录 运算符重载 1.概念 2.友元函数运算符重载 3.成员函数运算符重载 4.特殊运算符重载 1.赋值运算符重载 2.类型转换运算符重载 5.注意事项 std::string字符串类&#xff1a; 模板与容器 模板 1.函数模板 2.类模板 类内实现 类内声明类外实现 容器 1.标准模板库…

uniapp框架下scroll-view使用注意事项

在开发蓝牙调试app的过程&#xff0c;需要显示接收到的蓝牙硬件信息&#xff0c;主要需求是要求新收到的信息能够显示到显示区域。 如上图所示&#xff0c;第一个框为接受信息显示框&#xff0c;显示框在每次接收到信息化后自动向上滚动&#xff0c;以便显示最近收到的信息。 …

python爬虫案例——腾讯网新闻标题(异步加载网站数据抓取,post请求)(6)

文章目录 前言1、任务目标2、抓取流程2.1 分析网页2.2 编写代码2.3 思路分析前言 本篇案例主要讲解异步加载网站如何分析网页接口,以及如何观察post请求URL的参数,网站数据并不难抓取,主要是将要抓取的数据接口分析清楚,才能根据需求编写想要的代码。 1、任务目标 目标网…

总结拓展十一:S4 HANA和ECC区别

第一节 S/4 HANA系统简介 SAP系统的产品线 R/1版本——主要财务模块R/3版本——基本实现全模块ECC6.0——2005年推出&#xff08;ECC是2004年推出&#xff09;HANA——数据库产品——属于内存数据库BW on HANA——HANA与数据分析相结合 拓展&#xff1a; 数据库类型&#x…

EEPROM手册阅读笔记

目录 一、特征描述二、功能描述三、总线特性四、设备寻址五、写入操作1.字节写入2.页写入 六、读取操作1.当前地址读取2.随机读取3.顺序读取 一、特征描述 1.Microchip Technology Inc. 24AA04/24LC04B &#xff08;24XX04*&#xff09; 是一款 4 Kbit 电气可擦除 PROM。该器件…

初学者怎么入门大语言模型(LLM)?看完这篇你就懂了!

当前2024年&#xff0c;LLM领域发展日新月异&#xff0c;很多新的实用技术层出不穷&#xff0c;个人认为要跟上LLM的发展&#xff0c;需要掌握以下内容&#xff0c;并需要不断地跟踪学习。 入门LLM前置基础 深度学习基础知识&#xff1a;推荐李宏毅的深度学习课程Python和num…

STM32(三)GPIO输出、LED及蜂鸣器操作

一、GPIO 1.GPIO介绍 2.GPIO结构 stm32寄存器有32位&#xff0c;GPIO是16位&#xff0c;是stm32的低16位。 3.GPIO模式 4.GPIO应用电路 二、LED操作 1.操作GPIO的三个步骤 &#xff08;1&#xff09;使用RCC开启GPIO时钟 &#xff08;2&#xff09;使用GPIO初始函数初始化…

动态规划算法:10.路径问题_地下城游戏_C++

目录 题目链接&#xff1a;174. 地下城游戏 - 力扣&#xff08;LeetCode&#xff09; 一、题目解析 题目&#xff1a;​编辑 解析&#xff1a; 二、算法原理 1、状态表示 2、状态转移方程 状态转移方程推理&#xff1a; 3、初始化 dp表初始化: 特殊位置初始化&#…

【AcWing】基础算法

目录 1、快速排序 1.1 快速排序 1.2 第k个数 2、归并排序 2.1 归并排序 2.2 逆序对的数量 3、二分 3.1 数的范围 3.2 数的三次方根 4、高精度 4.1 高精度加法 4.2 高精度减法 4.3 高精度乘法 4.4 高精度除法 5、前缀和与差分 5.1 前缀和 5.2 子矩阵的和 5.3 …

基于jsp的图书馆管理系统的设计与实现 (含源码+sql+视频导入教程+文档)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于jsp的图书馆管理系统8拥有两种角色&#xff0c;分别为管理员和学生&#xff0c;具体功能如下&#xff1a; 管理员&#xff1a;图书管理、用户管理、违规处理、权限管理、个人信息修改…

某恩加密数据爬虫逆向分析

目标网站 aHR0cHM6Ly93d3cuZW5kYXRhLmNvbS5jbi9pbmRleC5odG1s 一、抓包分析 响应数据加密 二、逆向分析 下断点&#xff0c;刷新页面 一直往下跟栈&#xff0c;发现是在这进行的加密 内部实现逻辑 本地数据获取 本文章仅提供技术分享交流学习&#xff0c;不可对目标服务器造…

OpenAI最新GPT-o1-preview测评

OpenAI最新GPT-o1-preview测评 测试之后感觉这个相对GPT4o&#xff0c;能力上升了一个大的台阶&#xff0c;思考能力极强的最强GPT模型 之前用GPT4o测试过类似的题目&#xff0c;做的效果极差&#xff0c;答案直接就是错&#xff0c;这次GPT-o1-preview居然做对了&#xff0c;逻…

Ethernet 系列(3)-- 物理层测试::IOP Test::Cable diagnostics

车载以太网物理层IOP测试&#xff0c;即互操作性测试&#xff08;Interop- erability Tests&#xff09;&#xff0c;用于验证车载以太网PHY&#xff08;通常也称为收发器&#xff09;的可靠性和检查PHY能否在给定的有限时间内建立稳定的链路;还用于车载以太网PHY的诊断&#x…

窗口函数性能提升50倍,PawSQL索引推荐实战案例

&#x1f31f;引言 在数据驱动的现代世界&#xff0c;SQL查询的速度是应用程序快速响应的关键。尤其是那些涉及窗口函数的复杂查询&#xff0c;若缺乏恰当的索引支持&#xff0c;性能瓶颈可能会成为阻碍。本文将带您看看PawSQL是如何通过智能索引推荐&#xff0c;帮助一个包含…

《深度学习》—— 神经网络中常用的激活函数

文章目录 1. Sigmoid 激活函数2. Softmax 激活函数3. ReLU 激活函数4. Leaky ReLU 激活函数5. ELU 激活函数6. Tanh 激活函数 激活函数&#xff08;Activation Function&#xff09;是在人工神经网络的神经元上运行的函数&#xff0c;负责将神经元的输入映射到输出端。它在神经…

CVE-2024-4956实战

一、访问网页 二、公司信息域名收集 三、抓包读取敏感文件 Burpsuite抓包&#xff0c;修改GET请求即可&#xff08;GET /%2F%2F%2F%2F%2F%2F%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd HTTP/1.1 &#xff09;