【LeetCode、牛客】链表分割、链表的回文结构、160.相交链表

Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
🌱🌱个人主页:奋斗的明志
🌱🌱所属专栏:数据结构

在这里插入图片描述

📚本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。

在这里插入图片描述

链表面试题

  • 一、链表分割
    • 1. 题目
    • 2. 方法一解析
    • 3. 方法二解析
    • 4. 方法一完整代码
    • 5. 方法二完整代码
  • 二、链表的回文结构
    • 1. 了解链表的回文结构
    • 2. 题目
    • 3. 解析
    • 4. 完整代码
  • 三、相交链表
    • 1. 题目
    • 2. 解析
    • 3. 完整代码

一、链表分割

链表分割


1. 题目


在这里插入图片描述


2. 方法一解析


初始化准备:

ListNode newHead1 = new ListNode(0);
ListNode tmp1 = newHead1;
ListNode newHead2 = new ListNode(0);
ListNode tmp2 = newHead2;

newHead1tmp1 是用来存放小于 x节点的链表头当前节点
newHead2tmp2 是用来存放大于等于 x 节点的链表头当前节点
这里的 new ListNode(0) 是为了简化逻辑而创建的哨兵节点(dummy node),也就是虚拟节点不存储实际数据。

遍历原链表:

ListNode cur = pHead;
while (cur != null) {if (cur.val < x) {tmp1.next = cur;cur = cur.next;tmp1 = tmp1.next;} else {tmp2.next = cur;cur = cur.next;tmp2 = tmp2.next;}
}

使用 cur 作为遍历原链表 pHead 的指针。
如果 cur.val < x,将当前节点 cur 追加到 newHead1 的末尾,并更新 tmp1 指向最后一个节点。
如果 cur.val >= x,将当前节点 cur 追加到 newHead2 的末尾,并更新 tmp2 指向最后一个节点。
每次追加后,更新 cur 到下一个节点。

连接两个分区:

tmp2.next = null; // 将大于等于 x 的链表部分的末尾置空,避免形成环。
tmp1.next = newHead2.next; // 将小于 x 的链表部分的末尾连接到大于等于 x 的链表部分的头部。

返回结果:

return newHead1.next; // 返回重新排列后的链表头节点。

返回 newHead1.next,即小于 x 的部分的头节点,因为 newHead1 的头节点是一个哨兵节点


3. 方法二解析


在这里插入图片描述


  • 初始化变量:

bs, be: 分别表示小于 x 的部分的头节点和尾节点
as, ae: 分别表示大于等于 x 的部分的头节点和尾节点

  • 遍历链表:

使用 cur 指针遍历整个链表。
根据节点的值 cur.val 和给定的 x 进行判断,将节点加入对应的链表部分。

  • 连接两部分:

如果 bs(小于 x 的部分)为空,则直接返回 as(大于等于 x 的部分)的头节点。 否则,将 be(小于 x 的部分的尾节点)next 指向 as 的头节点,连接两部分链表。
最后,将 ae 的 next 设置为 null,防止出现循环链表

  • 返回结果:

返回重新排列后的链表的头节点 bs。


4. 方法一完整代码


  • 方法一:
import java.util.*;/*
public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}*/
public class Partition {public ListNode partition(ListNode pHead, int x) {if(pHead == null){return null;}if(pHead.next == null){return pHead;}ListNode newHead1 = new ListNode(0);ListNode tmp1 = newHead1;ListNode newHead2 = new ListNode(0);ListNode tmp2 = newHead2;ListNode cur = pHead;while(cur != null){if(cur.val < x){tmp1.next = cur;cur = cur.next;tmp1 = tmp1.next;}else{tmp2.next = cur;cur = cur.next;tmp2 = tmp2.next;}}tmp2.next = null;tmp1.next = newHead2.next;return newHead1.next;}
}

5. 方法二完整代码


import java.util.*;/*
public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}*/
public class Partition {public ListNode partition(ListNode pHead, int x) {if (pHead == null) {return null;}if (pHead.next == null) {return pHead;}ListNode cur = pHead;ListNode bs = null;ListNode be = null;ListNode as = null;ListNode ae = null;while (cur != null) {if (cur.val < x) {if (bs == null) {//说明一个节点都没有bs = cur;be = cur;} else {be.next = cur;be = be.next;}} else {if (as == null) {//说明一个节点都没有as = cur;ae = cur;} else {ae.next = cur;ae = ae.next;}}cur = cur.next;}if (bs == null) {return as;}be.next = as;if (as != null) {ae.next = null;}return bs;}
}

二、链表的回文结构

链表的回文结构

1. 了解链表的回文结构

链表的回文结构指的是链表从头到尾和从尾到头遍历得到的序列是相同的
换句话说,正序和逆序遍历得到的节点值序列完全一致

  • 判断链表是否回文的方法
    • 要判断一个链表是否为回文结构,可以采用以下方法之一:

    • 利用额外空间:

    • 将链表节点的值复制到数组中,然后利用数组的回文性质来判断。这种方法需要 O(n) 的额外空间,其中 n 是链表的长度。

    • 利用快慢指针和翻转:

      使用快慢指针找到链表的中点。
      将后半部分链表进行翻转。
      然后同时从头部和中点开始遍历比较节点值,看是否相等。
      最后恢复链表原始结构(可选)。


2. 题目


在这里插入图片描述


3. 解析


  • 空链表检查:
if (A == null) {return true;
}

如果输入的链表头节点 A 为空,直接返回 true,因为空链表被认为是回文的。

  • 找到中间节点:
    使用快慢指针法找到链表的中间节点:

在这里插入图片描述


在这里插入图片描述

ListNode fast = A;
ListNode slow = A;
while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;
}

快指针 fast 每次移动两步,慢指针 slow 每次移动一步,当快指针到达末尾时,慢指针恰好在链表的中间。

  • 反转后半部分链表:
    在这里插入图片描述
ListNode cur = slow.next;
while (cur != null) {ListNode curNext = cur.next;cur.next = slow;slow = cur;cur = curNext;
}

将从中间节点 slow.next 开始的链表部分进行反转,slow 成为反转后的头节点,最终 slow 指向反转后链表的尾节点。

  • 比较前半部分和后半部分链表:
  • 偶数情况见图:
    在这里插入图片描述
while (slow != A) {if (slow.val != A.val) {return false;}if (A.next == slow) {return true;}A = A.next;slow = slow.next;
}

通过两个指针 A 和 slow 分别从链表头和中间向两端移动,比较节点值是否相等。如果任何时候值不相等,则返回 false,表示不是回文链表;如果 A 和 slow 指向同一个节点,说明链表比较完毕,返回 true,表示是回文链表。

  • 总结:

这段代码通过快慢指针找到链表中间节点,反转后半部分链表,然后将前半部分和反转后的后半部分进行比较,来判断链表是否为回文链表。这种方法的时间复杂度为 O(n),空间复杂度为 O(1),是一种比较高效的实现方式。


4. 完整代码


import java.util.*;/*
public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}*/public class PalindromeList {public boolean chkPalindrome(ListNode A) {if(A == null){return true;}//1.找中间节点ListNode fast = A;ListNode slow = A;while(fast != null && fast.next != null){fast = fast.next.next;slow = slow.next;}//cur代表要反转的链表ListNode cur = slow.next;while(cur != null){ListNode curNext = cur.next;cur.next = slow;slow = cur;cur = curNext;}//一个向前,一个向后while(slow != A){if(slow.val != A.val){return false;}if(A.next == slow){return true;}A = A.next;slow = slow.next;}return true;}
}

三、相交链表

160.相交链表


1. 题目


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


2. 解析


在这里插入图片描述
在这里插入图片描述

  • 计算链表长度:

    • 首先通过遍历两个链表分别计算它们的长度 lenA 和 lenB。
  • 调整指针位置:

    • 将 pl 指向较长的链表头,ps 指向较短的链表头,以便后续步骤中两个指针同时遍历,确保它们从同一起点开始。
  • 移动指针到相同起点:

    • 如果两个链表长度不同,先让较长链表的指针 pl 先走 len 步,使得 pl 和 ps 位于同一起点。
  • 寻找交点:

    • 同时移动 pl 和 ps 直到它们相遇(即找到交点)或者同时到达链表尾部(即没有交点)。
  • 返回结果:

    • 如果找到了交点,返回交点节点;否则返回 null。

这种方法的时间复杂度是 O(m + n),其中 m 和 n 是两个链表的长度,因为需要分别遍历两个链表来计算长度和寻找交点。


3. 完整代码


/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode(int x) {*         val = x;*         next = null;*     }* }*/
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {//分别求两个链表的长度int lenA = 0;int lenB = 0;ListNode pl = headA;//永远指向最长的链表ListNode ps = headB;//永远指向最短的链表while(pl != null){lenA++;pl = pl.next;}while(ps != null){lenB++;ps = ps.next;}pl = headA;ps = headB;int len = lenA - lenB;if(len < 0){//说明 pl 应该指向 headBpl = headB;ps = headA;len = lenB - lenA;}//保证 len 一定是正数//pl 指向最长的//ps 指向最短的while(len != 0){pl = pl.next;len--;}//pl ps 走到相遇节点的路程是一样的while(pl != null && pl != ps){pl = pl.next;ps = ps.next;}if(pl == ps && pl == null){return null;}return pl;}
}

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

LangGPT结构化提示词编写实践

langGPT提示词 # Role: 浮点数比较助手 ## Profile - author: LangGPT - version: 1.0 - language: 中文 - description: 一个专门帮助用户进行浮点数比较的助手&#xff0c;确保LLM能够准确识别和对比浮点数。## Skills 1. 理解浮点数的结构和数值意义。 2. 精…

windows10 安装CUDA教程

如何在windows10系统上安装CUDA? 1、查看电脑的NVIDIA版本 nvidia-smi 2、官网下载所需CUDA版本 官网地址:https://developer.nvidia.com/cuda-toolkit-archive 我们所安装的CUDA版本需要小于等于本机电脑的NVIDIA版本。推荐使用迅雷下载,速度会更快哦。 3、安装步骤

解决Linux桌面初始化问题

问题 启动vnc桌面&#xff0c;提示问题 定位 从[t]csh手册 可以看到&#xff0c;其初始化流程 经定位&#xff0c;是.cshrc的这段代码存在&#xff0c;导致桌面初始化异常。 [wanlin.wangicinfra-cn-172-16-0-115 ~]$ cat .cshrc ...部分省略... # Environment for anac…

无涯·问知财报解读,辅助更加明智的决策

财报解读就像是给公司做一次全面的体检&#xff0c;是理解公司内部运作机制和市场表现的一把钥匙&#xff0c;能够有效帮助投资者、分析师、管理层以及所有市场参与者判断一家公司的健康程度和发展潜力。 星环科技无涯问知的财经库内置了企业年报及财经类信息&#xff0c;并对…

LeetCode/NowCoder-二叉树OJ练习

励志冰檗&#xff1a;形容在清苦的生活环境中激励自己的意志。&#x1f493;&#x1f493;&#x1f493; 目录 说在前面 题目一&#xff1a;单值二叉树 题目二&#xff1a;相同的树 题目三&#xff1a;对称二叉树 题目四&#xff1a;二叉树的前序遍历 题目五&#xff1a;另…

秋招突击——7/24——知识补充——JVM类加载机制

文章目录 引言类加载机制知识点复习类的生命周期1、加载2、连接——验证3、连接——准备4、连接——解析5、初始化 类加载器和类加载机制类加载器类加载机制——双亲委派模型 面试题整理1、类加载是什么2、类加载的过程是什么3、有哪些类加载器&#xff1f;4、双亲委派模型是什…

java面向对象进阶进阶篇--《JDK8,JDK9接口中新增的方法、接口的应用、适配器设计模式》

个人主页→VON 收录专栏→java从入门到起飞 接口→接口和接口与抽象类综合案例 一、JDK8接口中新增的方法 在JDK 8中&#xff0c;接口新增了几个重要的特性和方法&#xff0c;其中最显著的是默认方法&#xff08;Default Methods&#xff09;和静态方法&#xff08;Static Met…

Linux嵌入式学习——数据结构——线性表的链式结构

线性表的链式存储 解决顺序存储的缺点&#xff0c;插入和删除&#xff0c;动态存储问题。 特点&#xff1a; 线性表链式存储结构的特点是一组任意的存储单位存储线性表的数据元素&#xff0c;存储单元可以是连续的&#xff0c;也可以不连续。可以被存储在任意内存未被占…

使用lotusscript控制台吧!

大家好&#xff0c;才是真的好。 我们的公众号通常会涉及到很多lotusScript代码功能&#xff0c;写lotusScript代码时&#xff0c;我常常在想&#xff0c;这行语句明明是对的&#xff0c;为什么会有报错&#xff1f; 为此&#xff0c;常常会在语句中加入on error goto语句&am…

【Git多人协作开发】不同的分支下的多人协作开发模式

目录 0.前言背景 1.开发者1☞完成准备工作&协作开发 1.1查看分支情况 1.2创建本地分支feature-1 1.3三板斧 1.4push推本地分支feature-1到远程仓库 2.开发者2☞完成准备工作&协作开发 2.1创建本地分支feature-2 2.2三板斧 2.2push推送本地feature-2到远程仓库…

黑马JavaWeb企业级开发(知识清单)01——前端介绍,HTML实现标题:排版

文章目录 前言一、认识web前端、HTML、CSS二、VS Code开发工具&#xff08;插件弃用问题&#xff09;三、HTML结构标签介绍1. 标签页标题< title >2. 图片标签< img >1) 常见属性2) src路径书写方式 3. 标题标签< h >4. 水平分页线标签< hr > 四、用Vs…

生成树协议配置与分析

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、相关知识 1、生成树协议简介 生成树协议&#xff08;STP&#xff09;是一种避免数据链路层逻辑环路的机制&#xff0c;它通过信息交互识别环路并…

ZLMRTCClient配置说明与用法(含示例)

webRTC播放视频 后面在项目中会用到通过推拉播放视频流的技术&#xff0c;所以最近预研了一下webRTC 首先需要引入封装好的webRTC客户端的js文件ZLMRTCClient.js 下面是地址需要的自行下载 http://my.zsyou.top/2024/ZLMRTCClient.js 配置说明 new ZLMRTCClient.Endpoint…

AI/机器学习(计算机视觉/NLP)方向面试复习2

1. 用pytorch写一个self-attention 继承pytorch.nn.Module的类 代码&#xff1a; import torch import torch.nn as nn import torch.nn.functional as Fclass SelfAttention(nn.Module):def __init__(self, embed_size): # (B,T,C)super(SelfAttention, self).__init__()sel…

如何优化 Selenium 和 BeautifulSoup 的集成以提高数据抓取的效率?

摘要 在互联网时代&#xff0c;数据的价值日益凸显。对于电商网站如京东&#xff0c;其商品信息、用户评价等数据对于市场分析、产品定位等具有重要意义。然而&#xff0c;由于这些网站通常使用 JavaScript 动态生成内容&#xff0c;传统的爬虫技术难以直接获取到完整数据。本…

手机空号过滤批量查询的意义及方法

手机空号过滤批量查询是现代营销和通信管理中常用的技术手段&#xff0c;旨在通过批量处理手机号码&#xff0c;筛选出活跃号码和空号等无效号码&#xff0c;以提高营销效率和减少不必要的通信成本。以下是关于手机空号过滤批量查询的详细解答&#xff1a; 一、手机空号过滤批…

逆向笔记-某贴

逆向环境搭建 雷电模拟器9LsposedMagisk DeltaMTNP管理器算法助手2.1.2 软件链接&#xff1a; https://llzai.lanzouv.com/iWgV125h6vwj 密码:a0zy 主要注释代码 捕获窗口&#xff0c;查看日志&#xff0c;定位代码 找到show的里面的alertdialog的相关行都注释掉就好了&am…

HTML5-canvas1

1、canvas&#xff1a;创建画布 <canvas id"canvas"></canvas>2、画一条直线 var canvasdocument.getElementById(cancas&#xff09;; canvas.width800; canvas.height800; var contextcanvas.getContext(2d); //获得2d绘图上下文环境 //画一条直线 c…

全新AI工具——PaintsUndo:一键自动还原图像绘画过程!

ControlNet 作者 Lvmin Zhang 又开始整活了&#xff01;这次发布的PaintsUndo 只需要上传一张图片&#xff0c; 就能够一键生成绘画过程&#xff01;快来了解学习&#xff01; 1、核心技术 PaintsUndo 是一项突破性的技术&#xff0c;旨在通过输入静态图像&#xff0c;自动生…

基于vue-grid-layout插件(vue版本)实现增删改查/拖拽自动排序等功能(已验证、可正常运行)

前端时间有个需求&#xff0c;需要对33&#xff08;不一定&#xff0c;也可能多行&#xff09;的卡片布局&#xff0c;进行拖拽&#xff0c;拖拽过程中自动排序&#xff0c;以下代码是基于vue2&#xff0c;可直接运行&#xff0c;报错可评论滴我 部分代码优化来自于GPT4o和Clau…