LeetCode:经典题之141、142 题解及延伸
系列目录
88.合并两个有序数组
52.螺旋数组
567.字符串的排列
643.子数组最大平均数
150.逆波兰表达式
61.旋转链表
160.相交链表
83.删除排序链表中的重复元素
389.找不同
1491.去掉最低工资和最高工资后的工资平均值
896.单调序列
206.反转链表
92.反转链表II
141.环形链表
142.环型链表
目录
- 系列目录
- 141. 环形链表
- 常量因子
- 142. 环型链表II
141. 环形链表
🌟链表+哈希表+快慢指针
原题链接
C++
若未特殊标明,以下题解均写用C++
方法一 哈希表
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:bool hasCycle(ListNode *head) {// 无序集合(哈希集合) 变量类型为 ListNode*// 检查节点是否访问过unordered_set<ListNode*> seen;// head 不为空while (head) {// 这里 count的返回值只能是 0或1// 不能写成 seen.count(head) != nullif (seen.count(head) != 0)return true;// 节点不存在, 存入——seen.insert();// 避免无限循环导致超时seen.insert(head);head = head->next; }return false;}
};
方法二 快慢指针
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:bool hasCycle(ListNode *head) {// 如果 链表长度为0或1if (head == nullptr || head->next == nullptr)return false;ListNode* slow = head;ListNode* fast = head->next;while (slow != fast) {// 一定要先检查节点本身,避免出现 未定义行为// 链表长度为2if (fast == nullptr || fast->next == nullptr )return false;slow = slow->next;fast = fast->next->next;}return true;}
};
⚠️小细节:要先检查节点本身,再检查它的next
为什么 fast == nullptr
不能和 fast->next == nullptr
调换位置?
如果调换位置,先检查 fast->next == nullptr
,当链表中只有一个节点时(即 head
是唯一节点),fast
将会是 head->next
,它将是 nullptr
在这种情况下,fast->next
的检查(即 nullptr->next
)将会导致一个未定义行为(通常是一个运行时错误),因为我们不能在 nullptr
上解引用
所以,首先检查 fast
是为了确保在尝试访问 fast->next
之前,fast
不是 nullptr
,从而可以避免未定义行为
方法一 时间复杂度O(N) 空间复杂度O(N) 其中N为链表节点数
方法二 时间复杂度O(N) 空间复杂度O(1) 其中N为链表节点数
“相同”时间复杂度的两种算法,为什么实际执行时间差别这么大呢?
- 在实践中,快慢指针方法通常具有较小的常数因子,因为它只涉及指针操作和比较
- 虽然哈希表理论上的查找、插入的时间复杂度为O(1)——准确的说应该是平均O(1)
- 哈希表方法在插入和查找元素时可能需要进行哈希计算,这可能会引入额外的计算开销
- 但与其他数据结构相比,哈希表还是十分高效的,不必过于纠结
这里引入常量因子的概念
参考自《算法导论》
常量因子
又称常数因子
在C++代码中,常数因子经常以字面常量、const
变量或枚举类型的形式出现
这些常数因子可能用于定义数组的大小、循环的次数、数学计算中的系数、物理模拟中的常量等
字面常量
#include <iostream> int main() { const int arraySize = 100; // 数组大小的常数因子 int arr[arraySize]; // 使用字面常量作为数组大小 // 使用字面常量进行数学计算 double result = 3.14159 * 2 * 5; // π乘以直径,其中3.14159是π的近似值 std::cout << "Array size: " << arraySize << std::endl; std::cout << "Calculation result: " << result << std::endl; return 0;
}
const
变量
#include <iostream> int main() { const double gravity = 9.8; // 重力加速度的常数因子 double height = 10.0; // 初始高度 double time = std::sqrt(2 * height / gravity); // 使用常数因子计算自由落体时间 std::cout << "Time to fall from " << height << " meters: " << time << " seconds" << std::endl; return 0;
}
枚举类型
#include <iostream> enum class Color { RED = 1, // 颜色常量的一个值 GREEN = 2, BLUE = 3
}; int main() { Color myColor = Color::RED; // 使用枚举常量 switch (myColor) { case Color::RED: std::cout << "The color is red." << std::endl; break; // ... 其他情况 ... } return 0;
}
魔法数字(Magic Numbers)
在代码中直接使用字面常量而不是给它们命名可能会导致代码难以理解和维护
这些字面常量通常被称为“魔法数字” 为了改进代码的可读性和可维护性,最好将魔法数字替换为具有描述性名称的const
变量或枚举常量
性能优化中的常数因子
在性能优化的场景中,常数因子可能会变得很重要
例如,如果一个循环体内部有一个操作非常耗时,而这个操作是固定的(即不随循环迭代而变化),那么减少这个操作的执行次数(即减少常数因子)可能会显著提高性能
// 假设有一个耗时的操作doExpensiveOperation()
for (int i = 0; i < 1000; ++i) { // 这里的1000是一个常数因子 doExpensiveOperation(); // 假设这个操作非常耗时
} // 优化:如果可能的话,减少循环次数(即减少常数因子)
const int optimizedIterations = 500; // 假设这是优化后的常数因子
for (int i = 0; i < optimizedIterations; ++i) { doExpensiveOperation();
}
在上面的例子中,通过减少循环次数(即减少常数因子),我们可能能够显著提高代码的性能
但是,这种优化要在确保算法正确性和满足性能需求的前提下进行
142. 环型链表II
🌟链表+哈希表+快慢指针
原题链接
C++
若未特殊标明,以下题解均写用C++
方法一 哈希表
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *detectCycle(ListNode *head) {unordered_set<ListNode*> seen;while (head) {if (seen.count(head) != 0)// pos 不作为参数传递return head;seen.insert(head);head = head->next;}return nullptr;}
};
方法二 快慢指针
图示:
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode *slow = head, *fast = head;// 若没有环,fast 比 slow先指向空// 以此作为while 的循环条件判定while (fast) {// 如果链表长度为 1if (fast->next == nullptr)return nullptr;slow = slow->next;fast = fast->next->next;// 此时定义 *preif (fast == slow) {ListNode *pre = head;while (pre != slow) { pre = pre->next;slow = slow->next;}return pre;} }// 直到 fast指向空都没能满足 slow = fastreturn nullptr;}
};
相关文章:

LeetCode:经典题之141、142 题解及延伸
系列目录 88.合并两个有序数组 52.螺旋数组 567.字符串的排列 643.子数组最大平均数 150.逆波兰表达式 61.旋转链表 160.相交链表 83.删除排序链表中的重复元素 389.找不同 1491.去掉最低工资和最高工资后的工资平均值 896.单调序列 206.反转链表 92.反转链表II 141.环形链表 …...

rk3568 OpenHarmony 串口uart与电脑通讯开发案例
一、需求描述: rk3568开发板运行OpenHarmony4.0,通过开发板上的uart串口与电脑进行通讯,相互收发字符串。 二、案例展示 1、开发环境: (1)rk3568开发板 (2)系统:OpenHar…...
canvas画布旋转问题
先说一下为什么要旋转的目的:因为在画布上签名,在不同的设备上我需要不同方向的签名图片,电脑是横屏,手机就是竖屏,所以需要把手机的签名旋转270,因此写了这个方法。 关于画布旋转的重点就是获取到你的画布…...

vue3 【提效】自动导入框架方法 unplugin-auto-import 实用教程
是否还在为每次都需要导入框架方法而烦恼呢? // 每次都需手动导入框架方法 import { ref } from vuelet num ref(0)用 unplugin-auto-import 来帮你吧,以后只需这样写就行啦! let num ref(0)官方示例如下图 使用流程 1. 安装 unplugin-au…...

clip系列改进Lseg、 group ViT、ViLD、Glip
Lseg 在clip后面加一个分割head,然后用分割数据集有监督训练。textencoder使用clip,frozen住。 group ViT 与Lseg不同,借鉴了clip做了真正的无监督学习。 具体的通过group block来做的。使用学习的N个group token(可以理解为聚类…...
Ubuntu下TensorRT与trtexec工具的安装
新版(这里测试的是10.1版)的onnx转tensorrt engine工具trtexec已经集成在TensorRT中,不需要额外单独安装。 教程来源于此网页:https://medium.com/moshiur.faisal01/install-tensorrt-with-command-line-wrapper-trtexec-on-unun…...
MySQL定时任务
事件调度器操作 查看事件调度器是否开启:ON 表示已开启。 show variables like %event_scheduler%; ------------------------ | Variable_name | Value | ------------------------ | event_scheduler | ON | ------------------------ 开启和关闭事件调度器…...
Pandas实用Excel数据汇总
Pandas 是一个开源的 Python 库,由 Wes McKinney 开发,专门用于高效地处理和分析数据,无论是小规模的数据实验还是大规模的数据处理任务。它构建在 NumPy 之上,这意味着它利用了 NumPy 的高性能数组计算能力。Pandas 的核心数据结…...

【计算机网络】[第4章 网络层][自用]
1 概述 (1)因特网使用的TCP/IP协议体系(四层)的网际层,提供的是无连接、不可靠的数据报服务; (2)ATM、帧中继、X.25的OSI体系(七层)中的网络层,提供的是面向连接的、可靠的虚电路服务。 (3)路由选择分两种: 一种是由用户or管理员人工进行配置(只适用于规…...
Unity3D Entity_CacheService实现详解
Unity3D是一款广泛使用的游戏开发引擎,它提供了丰富的功能和工具来帮助开发者创建高质量的游戏和互动体验。在Unity开发过程中,资源管理是一个重要的环节,特别是当项目规模逐渐增大,资源数量变多时。为了优化资源的加载和管理&…...

DLMS/COSEM协议—(Green-Book)Gateway protocol
DLMS/COSEM协议 — Gateway protocol 10.10 Gateway protocol (网关协议)10.10.1 概述10.10.2 网关协议 (The gateway protocol)10.10.3 HES在WAN/NN中作为发起者(拉取操作)10.10.4 LAN中的终端设备作为发起…...
Android高级面试_12_项目经验梳理
Android 高级面试-1:Handler 相关 问题:Handler 实现机制(很多细节需要关注:如线程如何建立和退出消息循环等等) 问题:关于 Handler,在任何地方 new Handler 都是什么线程下? 问题:…...

【项目实训】解决前后端跨域问题
由于前端框架使用vue,后端使用flask,因此需要解决前后端通信问题 在vue.config.js中修改 module.exports defineConfig({transpileDependencies: true,lintOnSave:false, }) // 跨域配置 module.exports {devServer: { //记住&#x…...
Java反射API详解与应用场景
一、Java反射API简介: 一、什么是反射: 反射是一种强大的工具,它允许我们在运行时检查类、方法和字段的信息,甚至允许我们动态的调用特定类的方法或改变字段的值。编程语言中的反射机制通常用于从类、对象或方法中检索元数据,或者更特别的说,从代码本身中获取信息。这就…...

【例子】webpack 开发一个可以加载 markdown 文件的加载器 loader 案例
Loader 作为 Webpack 的核心机制,内部的工作原理却非常简单。接下来我们一起来开发一个自己的 Loader,通过这个开发过程再来深入了解 Loader 的工作原理。 这里我的需求是开发一个可以加载 markdown 文件的加载器,以便可以在代码中直接导入 m…...

揭秘!这款电路设计工具让学校师生都爱不释手——SmartEDA的魔力何在?
随着科技的飞速发展,电子设计已成为学校师生们不可或缺的技能之一。而在众多的电路设计工具中,有一款名为SmartEDA的工具,凭借其强大的功能和友好的用户体验,迅速赢得了广大师生的青睐。今天,就让我们一起探索SmartEDA…...
onlyoffice实现打开文档的功能
后端代码 import api from api import middlewareasync def doc_callback(request):data await api.req.get_json(request)print("callback ", data)# status 2 文档准备好被保存# status 6 文档编辑会话关闭return api.resp.success()app api.Api(routes[api.…...

基于 SpringBoot + Vue 的图书购物商城项目
本项目是一个基于 SpringBoot 和 Vue 的图书购物商城系统。系统主要实现了用户注册、登录,图书浏览、查询、加购,购物车管理,订单结算,会员折扣,下单,个人订单管理,书籍及分类管理,用…...

如何使用kimi智能助手:您的智能生活小助手
Kimi智能助手是一款功能强大的AI工具,旨在帮助用户提高工作效率和生活品质。下面小编将详细介绍如何使用Kimi智能助手,涵盖其主要功能以及一些实用技巧。 一、Kimi智能助手的主要功能 多语言对话能力:Kimi擅长中文和英文的对话,可…...
sql操作
1. 按条件将表A的数据更新到表B中: update B b set b.col1 (select col1 from A a where b. id a.code), b.col2 (select col2 from A a where b. id a.code), ………… 2. 将表A的全量数据插入到表B中 insert into B (col1, col2, col3, col4,……&am…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...