【LeetCode Hot100 链表(上)】相交链表、反转链表、回文链表、环形链表、合并两个有序链表、两数相加

链表

  • 1. 相交链表
    • 问题描述
    • 解决思路
    • 代码实现
  • 2. 反转链表
    • 问题描述
    • 解决思路
    • 代码实现
  • 3. 回文链表
    • 问题描述
    • 解决思路
    • 代码实现
  • 4. 环形链表
    • 问题描述
    • 解决思路
    • 代码实现
  • 5. 环形链表II
    • 问题描述
    • 解决思路
    • 代码实现
  • 6. 合并两个有序链表
    • 问题描述
    • 解决思路
    • 代码实现
  • 7. 两数相加
    • 问题描述
    • 解决思路
    • 代码实现

1. 相交链表

问题描述

给定两个单链表 headAheadB,它们可能在某个节点相交。请编写一个函数来查找它们的第一个交点。若没有交点,返回 null

解决思路

  1. 计算链表的长度:首先,遍历两个链表,分别计算它们的长度 lenAlenB

  2. 调整起始点:确定较长链表的起始位置,使得两个链表的剩余部分长度相同。通过让较长链表先走长度差步,保证两个链表在相同的“距离剩余部分”的起点上对齐。

  3. 同步遍历:同步遍历两个链表,如果它们的当前节点相同,则返回该节点作为交点。如果遍历结束都没有找到交点,返回 null

代码实现

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {int lenA = 0, lenB = 0;ListNode curA = headA;ListNode curB = headB;// 计算链表A和B的长度while (curA != null) {lenA++;curA = curA.next;}while (curB != null) {lenB++;curB = curB.next;}curA = headA;curB = headB;// 让curA为最长链表的头,lenA为其长度if (lenB > lenA) {// 交换(lenA, lenB)int tmpLen = lenA;lenA = lenB;lenB = tmpLen;// 交换(curA, curB)ListNode tmpNode = curA;curA = curB;curB = tmpNode;}// 求长度差int gap = lenA - lenB;// 让curA和curB在同一起点上(末尾位置对齐)while (gap-- > 0) {curA = curA.next;}// 现在在同一起点上同步遍历while (curA != null) {if (curA == curB) return curA;  // 找到交点curA = curA.next;curB = curB.next;}return null;  // 没有交点}
}

2. 反转链表

问题描述

给定一个单链表的头节点 head,请编写一个函数来反转该链表,并返回反转后的链表。

解决思路

  1. 初始化

    • 创建三个指针:cur 指向当前节点,pre 指向前一个节点,temp 用来暂存当前节点的下一个节点。
  2. 反转操作

    • 遍历链表的每个节点。在遍历过程中,将当前节点的 next 指针指向前一个节点,从而实现链表的反转。
    • 使用 cur.next = pre 将当前节点与前一个节点连接,然后将 pre 更新为当前节点,cur 更新为下一个节点。
  3. 结束遍历

    • curnull 时,遍历结束,此时 pre 就是反转后的链表的头节点。
  4. 返回结果

    • 返回 pre,即反转后的链表的头节点。

代码实现

public class Solution {public ListNode reverseList(ListNode head) {ListNode cur = head;  // 当前节点ListNode pre = null;  // 前一个节点ListNode temp = null; // 临时节点,保存当前节点的下一个节点while (cur != null) {temp = cur.next;  // 暂存当前节点的下一个节点cur.next = pre;   // 反转当前节点的指针pre = cur;        // 移动前一个节点指针cur = temp;       // 移动当前节点指针}return pre;  // 返回反转后的链表头节点}
}

3. 回文链表

问题描述

给定一个单链表的头节点 head,判断该链表是否为回文链表。回文链表是指从前往后和从后往前读的链表内容一致。

解决思路

  1. 寻找链表的中间节点

    • 使用快慢指针法,快指针 fast 每次移动两步,慢指针 slow 每次移动一步。当快指针到达链表末尾时,慢指针正好指向链表的中间节点。
  2. 反转链表的后半部分

    • 从中间节点开始,将链表的后半部分反转,这样就能方便地和前半部分进行比较。
  3. 比较前半部分和反转后的后半部分

    • 比较链表的前半部分和反转后的后半部分的节点值。如果有任何不相等的节点,说明链表不是回文链表。
  4. 返回结果

    • 如果没有发现不相等的节点,说明链表是回文的。

代码实现

public class Solution {public boolean isPalindrome(ListNode head) {// 找到中间节点,把后半部分反转,然后比较ListNode middle = getMiddle(head);ListNode head2 = reverseList(middle);// 获得的反转链表长度只有原来的一半, 所以这里用head2来做循环停止条件while (head2 != null) {if (head.val != head2.val) {return false;}head = head.next;head2 = head2.next;}return true;}// 快慢指针,找到链表的中间节点public ListNode getMiddle(ListNode head) {ListNode fast = head;ListNode slow = head;while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}return slow;}// 反转链表public ListNode reverseList(ListNode head) {ListNode p = null;ListNode q = head;while (q != null) {ListNode tmp = q.next;q.next = p;p = q;q = tmp;}return p;}
}

4. 环形链表

问题描述

给定一个单链表 head,判断该链表是否有环。若链表中存在环,则返回 true;否则返回 false

解决思路

使用 快慢指针(Floyd’s Cycle Detection Algorithm,也叫快慢指针法)来判断链表中是否有环。具体步骤如下:

  1. 初始化指针

    • 使用两个指针,慢指针 slow 每次向后移动一步,快指针 fast 每次向后移动两步。
  2. 循环遍历链表

    • 每次移动慢指针和快指针,直到快指针到达链表的末尾(即没有环的情况)。
    • 如果快指针和慢指针相遇,则说明链表中存在环。
  3. 处理特殊情况

    • 如果链表为空或者只有一个节点时,直接返回 false,因为没有环。

代码实现

public class Solution {public boolean hasCycle(ListNode head) {// 特殊情况判断:链表为空或只有一个节点if (head == null || head.next == null) {return false;}ListNode slow = head;          // 慢指针ListNode fast = head.next;     // 快指针// 快慢指针遍历链表while (slow != fast) {// 如果快指针到达链表末尾,则说明没有环if (fast == null || fast.next == null) {return false;}// 移动慢指针和快指针slow = slow.next;fast = fast.next.next;}// 快慢指针相遇,说明有环return true;}
}

5. 环形链表II

问题描述

给定一个链表,如果链表中存在环,返回环的起始节点;否则,返回 null

解决思路

  1. 使用哈希集合

    • 我们可以通过遍历链表并将每个节点存储到一个哈希集合中。如果某个节点已经存在于集合中,则说明链表有环,返回该节点。
    • 如果链表没有环,那么遍历完链表所有节点后,集合不会重复任何元素,最终返回 null
  2. 时间复杂度

    • 每个节点最多会被访问一次,因此时间复杂度是 O(n),其中 n 是链表的长度。
  3. 空间复杂度

    • 由于使用了哈希集合来存储链表节点,因此空间复杂度为 O(n),其中 n 是链表的长度。

代码实现

public class Solution {public ListNode detectCycle(ListNode head) {// 用哈希集合来记录访问过的节点Set<ListNode> seen = new HashSet<>();// 遍历链表while (head != null) {// 如果当前节点已经出现过,说明存在环,返回当前节点if (!seen.add(head)) {return head;}// 将当前节点的下一个节点继续遍历head = head.next;}// 链表没有环,返回nullreturn null;}
}

6. 合并两个有序链表

问题描述

给定两个有序链表 list1list2,将它们合并成一个有序链表,并返回新的链表。

解决思路

我们可以使用一个虚拟的头节点 head3,通过逐步遍历 list1list2,按顺序将它们的节点加入到新链表中。

  1. 虚拟头节点:通过引入虚拟头节点,简化了合并操作,避免了在合并过程中的特殊情况处理(例如初始时没有头节点)。
  2. 遍历两个链表:同时遍历两个链表,比较它们的节点值,将较小的节点加入新链表。
  3. 处理剩余节点:在某一链表遍历结束后,直接将新链表的尾部指向另一个链表的剩余部分。
  4. 返回结果:最终返回虚拟头节点的 next,即合并后的链表。

代码实现

public class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode head3 = new ListNode(); // 虚拟头节点ListNode cur = head3; // 当前指针,指向新链表的尾部// 同时遍历两个链表,直到其中一个链表为空while (list1 != null && list2 != null) {if (list1.val <= list2.val) {cur.next = list1;list1 = list1.next; // 移动 list1 指针} else {cur.next = list2;list2 = list2.next; // 移动 list2 指针}cur = cur.next; // 移动当前指针}// 合并后,只有一个链表可能没有遍历完,直接将未遍历完的链表接到新链表的末尾cur.next = (list1 == null) ? list2 : list1;// 返回新链表的头节点return head3.next;}
}

7. 两数相加

问题描述

给定两个非空链表,表示两个非负整数。数字按逆序存储,每个节点包含一个数字。将这两个数相加,返回一个新的链表表示它们的和。

解决思路

  1. 模拟逐位相加

    • 从两个链表的头节点开始,对应位的数值相加。若有进位,则加到下一位。
    • 如果某个链表已经遍历完,认为它对应的数为0,继续计算。
    • 最后,如果仍有进位,需要在链表末尾添加一个新的节点。
  2. 进位处理

    • 进位通过 carry 变量来管理,逐位传递到下一个节点。
  3. 链表结构

    • 使用一个虚拟链表(通过 headtail)来构建结果链表。

代码实现

public class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode head = null, tail = null; // 用于构建结果链表int carry = 0; // 进位// 遍历链表,直到两个链表都为空while (l1 != null || l2 != null) {// 如果某个链表到达末尾,则认为该链表对应的值为0int n1 = (l1 != null) ? l1.val : 0;int n2 = (l2 != null) ? l2.val : 0;int sum = n1 + n2 + carry; // 计算当前位的和(包含进位)// 如果是第一个节点if (head == null) {head = new ListNode(sum % 10); // 取个位数作为新节点tail = head; // `tail` 指向新节点} else {tail.next = new ListNode(sum % 10); // 创建新节点并添加到链表tail = tail.next; // 更新 `tail` 指针}carry = sum / 10; // 计算进位,传递到下一个节点// 移动到下一个节点if (l1 != null) {l1 = l1.next;}if (l2 != null) {l2 = l2.next;}}// 如果最终有进位,添加一个新节点if (carry > 0) {tail.next = new ListNode(carry);}return head; // 返回结果链表的头节点}
}

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

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

相关文章

【架构】分层架构 (Layered Architecture)

一、分层模型基础理论 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/0365cf0bfa754229bdedca6b472bffc7.png 1. 核心定义 分层架构(Layered Architecture)模型是一种常见的软件设计架构,它将软件系统按照功能划分为不同的层次,每个层次都有特定的职责和功能…

2024年国赛高教杯数学建模C题农作物的种植策略解题全过程文档及程序

2024年国赛高教杯数学建模 C题 农作物的种植策略 原题再现 根据乡村的实际情况&#xff0c;充分利用有限的耕地资源&#xff0c;因地制宜&#xff0c;发展有机种植产业&#xff0c;对乡村经济的可持续发展具有重要的现实意义。选择适宜的农作物&#xff0c;优化种植策略&…

捷米特 JM - RTU - TCP 网关应用 F - net 协议转 Modbus TCP 实现电脑控制流量计

一、项目背景 在某工业生产园区的供水系统中&#xff0c;为了精确监测和控制各个生产环节的用水流量&#xff0c;需要对分布在不同区域的多个流量计进行集中管理。这些流量计原本采用 F - net 协议进行数据传输&#xff0c;但园区的监控系统基于 Modbus TCP 协议进行数据交互&…

遥感影像目标检测:从CNN(Faster-RCNN)到Transformer(DETR)

我国高分辨率对地观测系统重大专项已全面启动&#xff0c;高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成&#xff0c;将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB&#xff0c;遥感大数据时…

iOS事件传递和响应

背景 对于身处中小公司且业务不怎么复杂的程序员来说&#xff0c;很多技术不常用&#xff0c;你可能看过很多遍也都大致了解&#xff0c;但是实际让你讲&#xff0c;不一定讲的清楚。你可能说&#xff0c;我以独当一面&#xff0c;应对自如了&#xff0c;但是技术的知识甚多&a…

【核心算法篇十三】《DeepSeek自监督学习:图像补全预训练方案》

引言:为什么自监督学习成为AI新宠? 在传统监督学习需要海量标注数据的困境下,自监督学习(Self-Supervised Learning)凭借无需人工标注的特性异军突起。想象一下,如果AI能像人类一样通过观察世界自我学习——这正是DeepSeek图像补全方案的技术哲学。根据,自监督学习通过…

轻松搭建本地大语言模型(二)Open-WebUI安装与使用

文章目录 前置条件目标一、安装 Open-WebUI使用 Docker 部署 二、使用 Open-WebUI&#xff08;一&#xff09;访问Open-WebUI&#xff08;二&#xff09;注册账号&#xff08;三&#xff09;模型选择&#xff08;四&#xff09;交互 四、常见问题&#xff08;一&#xff09;容器…

零基础学QT、C++(一)安装QT

目录 如何快速学习QT、C呢&#xff1f; 一、编译器、项目构建工具 1、编译器&#xff08;介绍2款&#xff09; 2、项目构建工具 二、安装QT 1、下载QT安装包 2、运行安装包 3、运行QT creator 4、导入开源项目 总结 闲谈 如何快速学习QT、C呢&#xff1f; 那就是项目驱动法&…

vue取消全选功能按钮注意事项

这里这个功能是通过各种条件查出数据,但只取一条数据进行后续业务,虽然每一条数据前面都有多选框,但只需要选一个,所以在业务上分析可以把这个全选按钮取消掉 这里不是简单的把多选组件的selection-change"handleSelectionChange"和handleSelectionChange方法去掉,因…

【再读】2501.12948/DeepSeek-R1通过强化学习提升大型语言模型(LLMs)的推理能力

DeepSeek-R1-Zero展示了在没有监督数据的情况下&#xff0c;通过RL可以发展出强大的推理能力。DeepSeek-R1通过引入冷启动数据和多阶段训练&#xff0c;进一步提升了推理性能&#xff0c;达到了与OpenAI-o1-1217相当的水平。此外&#xff0c;通过蒸馏技术&#xff0c;将DeepSee…

校园网架构设计与部署实战

一、学习目标 掌握校园网分层架构设计原则 理解多业务VLAN规划方法 学会部署认证计费系统 实现基础网络安全防护 二、典型校园网场景 需求分析&#xff1a;某中学需建设新型校园网络 覆盖教学楼/宿舍/图书馆三区域 区分教师/学生/访客网络权限 满足2000终端并发接入 …

leetcode:942. 增减字符串匹配(python3解法)

难度&#xff1a;简单 由范围 [0,n] 内所有整数组成的 n 1 个整数的排列序列可以表示为长度为 n 的字符串 s &#xff0c;其中: 如果 perm[i] < perm[i 1] &#xff0c;那么 s[i] I 如果 perm[i] > perm[i 1] &#xff0c;那么 s[i] D 给定一个字符串 s &#xff0…

数仓搭建(hive):DWS层(服务数据层)

DWS层示例: 搭建日主题宽表 需求 维度 步骤 在hive中建数据库dws >>建表 CREATE DATABASE if NOT EXISTS DWS; 建表sql CREATE TABLE yp_dws.dws_sale_daycount( --维度 city_id string COMMENT 城市id, city_name string COMMENT 城市name, trade_area_id string COMME…

网工项目实践2.8 IPv6设计及网络优化需求分析及方案制定

本专栏持续更新&#xff0c;整一个专栏为一个大型复杂网络工程项目。阅读本文章之前务必先看《本专栏必读》。 全网拓扑展示 一.IPV6部署规划 在北京总部&#xff0c;为了迎接未来网络的发展&#xff0c;规划在BJ_G2、BJ_G3、BJ_C1、BJ_C2之间运行IPv6协议&#xff0c;以建立I…

50页PDF|数字化转型成熟度模型与评估(附下载)

一、前言 这份报告依据GBT 43439-2023标准&#xff0c;详细介绍了数字化转型的成熟度模型和评估方法。报告将成熟度分为五个等级&#xff0c;从一级的基础转型意识&#xff0c;到五级的基于数据的生态价值构建与创新&#xff0c;涵盖了组织、技术、数据、资源、数字化运营等多…

DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方DeepSeek接入)

前言 在当今数字化时代&#xff0c;AI编程助手已成为提升开发效率的利器。DeepSeek作为一款强大的AI模型&#xff0c;凭借其出色的性能和开源免费的优势&#xff0c;成为许多开发者的首选。今天&#xff0c;就让我们一起探索如何将DeepSeek接入PyCharm&#xff0c;实现高效、智…

阐解WiFi信号强度

WiFi信号强度是指无线网络信号的强度&#xff0c;通常以负数dB&#xff08;分贝&#xff09;来表示。信号越强&#xff0c;dB值越接近零。WiFi信号强度直接影响你的网络速度、稳定性和连接的可靠性。简单来说&#xff0c;WiFi信号越强&#xff0c;你的设备与路由器之间的数据传…

MySQL数据类型

目录 1、数据类型分类 2、数值类型 2.1.tinyint类型 2.2.bit类型 2.3.小数类型 2.3.1.float 2.3.2.decimal 3.字符串类型 3.1.char 3.2.varchar 3.3 char和varchar比较 4.日期和时间类型 5.enum和set 语法&#xff1a; 案例&#xff1a; 1、数据类型分类 2、数值…

【Spring+MyBatis】_图书管理系统(下篇)

图书管理系统上篇、中篇如下&#xff1a; 【SpringMyBatis】_图书管理系统&#xff08;上篇&#xff09;-CSDN博客 【SpringMyBatis】_图书管理系统&#xff08;中篇&#xff09;-CSDN博客 目录 功能5&#xff1a;删除图书 6.1 约定前后端交互接口 6.2 后端接口 6.3 前端…

两个实用且热门的 Python 爬虫案例,结合动态/静态网页抓取和反爬策略,附带详细代码和实现说明

在这个瞬息万变的世界里&#xff0c;保持一颗探索的心&#xff0c;永远怀揣梦想前行。即使有时会迷失方向&#xff0c;也不要忘记内心深处那盏指引你前进的明灯。它代表着你的希望、你的信念以及对未来的无限憧憬。每一个不曾起舞的日子&#xff0c;都是对生命的辜负&#xff1…