自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(133)
  • 收藏
  • 关注

原创 CSS表达式——上篇【selenium】

本文章仅作自己学习笔记用途,转载自,侵权联系删除~前面我们看到了根据 id、class属性、tag名 选择元素。如果我们要选择的 元素 没有id、class 属性,或者有些我们不想选择的元素 也有相同的 id、class属性值,怎么办呢?这时候我们通常可以通过语法选择元素。

2025-07-09 10:30:58 17

原创 二分查找篇——搜索二维矩阵【LeetCode】排除法

该算法充分利用了矩阵的有序性质,采用了极具技巧性的搜索策略:✅ 从「右上角」出发,能够在每一步排除整行或整列,使搜索过程呈现出单调线性收敛。✅ 每次移动都让搜索空间减少一行或一列,效率远高于暴力遍历。✅ 逻辑直观,不容易出错,尤其适用于不要求二分但矩阵有序性强的场景。✅ 属于典型的「Z字形搜索」策略,也可用于拓展如:LeetCode 240、类似地形图搜索等题。while i < m and j >= 0: # 还有剩余元素return True # 找到 target。

2025-07-09 01:00:00 137

原创 二分查找篇——搜索二维矩阵【LeetCode】二分查找法

left = -1使用这种技巧可以保证二分时永远不会漏掉元素,同时是经典的循环条件。该算法的关键技巧是:✅利用二维矩阵的单调性将其抽象为一维有序数组,直接进行二分查找。✅ 用mid // n和mid % n将一维下标还原为二维坐标,无需额外展开数据结构。✅ 使用left = -1的二分模板写法,属于「偏左二分」,可以有效避免边界条件出错。✅ 整个逻辑不需要任何额外空间,运行效率极高。这是一种典型的、面试中极受欢迎的“空间压缩 + 二分”优化手法。

2025-07-09 01:00:00 184

原创 二分查找篇——搜索二维矩阵【LeetCode】遍历法

该算法核心非常简单直接:✅暴力穷举法:遍历整个二维数组逐个比对元素;❌未利用矩阵的有序特性,没有进行任何剪枝或优化;✅ 实现简单,容易理解;❌ 对于大数据量输入效率较低。换句话说,这是最基础的解法(Baseline),适合初学者理解,但在面试或实际场景中不推荐使用。这是一种最朴素的暴力搜索解法,时间复杂度为 O(M×N),空间复杂度 O(1),实现简单但未利用矩阵的有序性质,适合新手理解,不适合实际使用或面试场景,可进一步优化为「逐行二分查找」或「二维 -> 一维映射 + 二分」的高效解法。

2025-07-08 20:25:26 140

原创 二分查找篇——搜索插入位置【LeetCode】三种写法,python2/python3

left = 0,注意这里right是开区间(不包括数组最后一位索引);区间表示搜索空间。✅ 本质是对数组使用左闭右开区间的二分查找模板。✅ 核心目标是实现,即查找第一个>= target的下标。✅模式是标准实现技巧;✅ 最终返回的是合法插入位置,可以统一处理「存在与否」。left = 0else:return left # 或者right。

2025-07-08 20:09:10 277

原创 操控元素的基本方法【selenium】

如果你想获取元素的某个 HTML 属性,比如 class、href、value 等,可以用。最后,如果你希望在自动化操作完成后关闭浏览器窗口,可以调用 WebDriver 的。在使用 Selenium 定位到网页中的某个元素之后,我们会获得一个。如果你了解 HTML 和 JS,你会发现 Selenium 的。,这个对象就像是“遥控器”,可以用来控制这个具体的页面组件。等表单输入控件,如果你想拿到用户输入的内容,方法,其实就是通过 JS 去读取元素的属性。输入文字的方式也很直观,使用。

2025-07-08 11:39:49 184

原创 选择元素的基本方法【selenium】

在使用 Selenium 自动化测试或数据采集时,一个常见任务就是模拟人在浏览器中输入关键词进行搜索。这类操作本质上是“控制网页中的界面元素”。也就是说,在输入、点击之前,必须让程序知道我们想控制的是哪一个元素。这会让 Selenium 在查找元素时,如果没找到,不会立刻报错,而是每隔 0.5 秒重新尝试一次,最多尝试到 10 秒。的本质,是通过元素的某些“特征”来让浏览器识别出你想操作的对象。这时,页面中某个控件的 HTML 标签会高亮显示,我们就可以看到它的。(注意复数),返回的是一个元素列表。

2025-07-08 11:30:01 386

原创 Selenium 原理【selenium】

自动化脚本 → 调用客户端库 → 客户端发送命令 → 浏览器驱动接收→ 控制浏览器执行 → 获取执行结果 → 返回给脚本 → 脚本处理结果。

2025-07-08 10:59:04 265

原创 回溯题解——电话号码的字母组合【LeetCode】

通常输入最多11位手机号,组合数也就几千个,DFS 是可以接受的。个数字映射 3 个字符(如 2、3、4、5、6、8),字符串与电话按键的映射,数字 2~9 映射到相应字母。每一层 DFS 对应一个数字(一个位置),每一层会有。每个数字最多映射 4 个字母(最多的是 7 和 9)。),避免字符串拼接频繁生成新对象(效率优化)。索引从 0 开始,为方便直接用数字下标查询。位开始,依次选择可能的字符,递归构建组合。遍历当前数字对应的所有字符,例如。对于每个组合,生成字符串的时间是。主函数,接收一个字符串。

2025-07-08 00:01:00 296

原创 回溯题解——子集【LeetCode】输入的视角(选或不选)

这是一种更容易理解、便于剪枝的通用枚举方式,相比位运算法更直观(适合初学者理解和复杂问题扩展)。开始,做“选 or 不选”的子集构造。到达数组末尾,表示一种完整子集构造完成。开始,表示从第一个元素开始构造子集。每次递归最多生成一个子集,长度最多为。每个元素有两个选择:选 or 不选。回溯上一步,探索下一个可能性。次(每个元素选 or 不选)。,每层递归函数栈消耗是常量级。个子集,每个子集长度最多为。撤销选择,回溯到上一状态。每条路径就是一个合法子集。存储当前路径,最大长度为。(递归 + path)。

2025-07-07 23:24:29 304

原创 回溯题解——子集【LeetCode】二进制枚举法

这是一种非常高效、简洁的生成子集的方式,尤其适用于集合元素较少(如 n ≤ 20)的场景。的二进制表示就是一个子集的“选取方案”,每一位表示该位置元素选不选。位二进制数表示(0 表示不选,1 表示选)。,每个整数的二进制形式唯一表示一个子集。每次生成一个子集使用一个列表(临时变量。个子集,每个最多判断 3 个位置。位运算用于高效判断哪些元素被选中。所以总的空间用于保存输出结果是。的简写方式,表示子集的总数。,就说明这个元素被选入子集。将每一个子集的选取用一个。位是否为1的经典写法。(第0和第2位是1)。

2025-07-07 23:15:21 317

原创 测试高频常见面试场景题汇总【持续更新版】

💡 1. 功能测试 2. 性能测试 3. 安全测试 4. 兼容性测试 5. 用户体验测试 6. 异常处理测试。:验证用户能否选择不同的支付方式(如信用卡、支付宝、微信等)。:验证登录功能在不同设备(手机、平板、PC)下的表现。:验证支付功能在不同设备(手机、平板、PC)下的表现。:验证用户使用正确的用户名和密码能否成功登录。:验证用户未输入用户名或密码时能否正确提示。:验证用户余额不足时支付功能的处理能力。:验证用户使用错误密码时能否正确提示。:验证登录功能的响应时间是否符合要求。

2025-07-06 17:54:11 869

原创 回溯题解——全排列【LeetCode】

该算法的核心是:使用回溯(DFS)方式按位构建排列,每一层递归尝试将所有未使用的数字填入当前位置,通过布尔数组标记状态,避免重复选择,实现全排列。✅ 回溯模板典型写法(构造 + 撤销);✅ 使用显式路径数组path[i]来记录当前位置数字;✅ 使用布尔标记数组on_path控制元素是否被使用;✅ 整体结构是“选择—递归—撤销选择”的排列构造范式。

2025-07-06 14:00:00 571

原创 二叉树题解——二叉搜索树中第 K 小的元素【LeetCode】使用外部变量ans记录答案

利用 BST 的中序遍历特性,使节点值按升序访问,倒数计数直到第 k 个元素,即为结果。✅ 利用了 BST 的有序性,不需要额外排序;✅ 通过中序遍历直接按顺序找到第 k 个元素;✅ 使用k == 0作为提前剪枝条件,节省时间;✅ 用nonlocal管理共享变量,递归写法清晰优雅。

2025-07-05 13:56:12 387

原创 二叉树题解——验证二叉搜索树【LeetCode】后序遍历

后序遍历地收集每棵子树的最值信息,同时判断当前节点是否满足 BST 性质。✅ 通过最小/最大值来传递合法性,思路独特;✅ 利用作为非法标志,避免使用全局变量;✅ 后序遍历先处理左右子树,再判断当前节点,能做到“非法剪枝”;✅ 可扩展性强:该模式也可以改写为同时处理 AVL 树、红黑树的平衡性检测等。# 也可以在递归完左子树之后立刻判断,如果发现不是二叉搜索树,就不用递归右子树了= inf本算法通过后序遍历传递(最小值, 最大值)

2025-07-04 18:15:23 307

原创 二叉树题解——验证二叉搜索树【LeetCode】前序遍历

递归地对每个节点维护上下边界区间,判断其值是否符合 BST 的定义,并递归验证左右子树。✅ 采用“值域约束”方式,严格验证 BST 的定义✅ 上下界会随着递归深入而收紧,更精确限制节点取值✅ 非常适合处理“全局性条件”的验证场景,如 BST 中的跨层约束✅ 简洁高效,是判断 BST 有效性的经典做法本算法通过上下界约束方式递归判断每个节点是否符合 BST 条件,时间复杂度 O(n),空间复杂度 O(h),是判断有效二叉搜索树的最经典、最推荐方案之一。

2025-07-04 13:58:15 302

原创 二叉树题解——将有序数组转换为二叉搜索树【LeetCode】优化解法

分治 + 递归思想,选中点为根节点,递归构建左右子树,保持树的高度平衡。✅ 使用数组中点作为当前子树的根节点,有效保证平衡性;✅ 不断分割区间构建左右子树,天然匹配树的结构;✅ 用索引代替切片,避免多余内存开销;✅ 是将“数组 → 树结构”的典型构造模板。本算法通过分治递归+中点选根策略,在 O(n) 时间、O(log n) 空间内将有序数组构造成一棵平衡的 BST,是数组转树结构的经典构造技巧。利用递归 + 数组切片 + 中点选根策略,构造高度平衡的 BST。

2025-07-04 09:41:32 1169

原创 二叉树题解——将有序数组转换为二叉搜索树【LeetCode】传统解法

选择任意一个中间位置数字作为根节点,则根节点的下标为 mid=(left+right)/2 和 mid=(left+right+1)/2 两者中随机选择一个,此处的除法为整数除法。选择中间位置右边的数字作为根节点,则根节点的下标为 mid=(left+right+1)/2,此处的除法为整数除法。选择中间位置左边的数字作为根节点,则根节点的下标为 mid=(left+right)/2,此处的除法为整数除法。

2025-07-04 09:22:55 545

原创 二叉树题解——二叉树的层序遍历【LeetCode】队列实现

利用deque实现队列结构,避免了列表pop(0)带来的性能损耗。✅popleft()是 O(1) 时间复杂度;✅能精确处理一层;✅ 代码结构更标准、更高效,更适合大型数据量的广度优先遍历。return []ans = []while q:vals = []return ans该队列版层序遍历通过deque优化了队列操作,是广度优先搜索在树结构上的最标准实现,在 O(n) 时间和 O(n) 空间复杂度下,稳定、高效、易读,是生产代码中常用的 BFS 模板之一。

2025-07-03 20:44:56 319

原创 二叉树题解——二叉树的层序遍历【LeetCode】数组实现

本算法的核心是:使用广度优先遍历(BFS),每次处理一整层,借助两个列表cur和nxt来模拟队列层层推进。✅ 不使用或,但逻辑上一样;cur(当前层),nxt(下一层),vals(记录值);✅ 是 BFS 在树结构上的最标准用法之一。return []ans = []while cur:nxt = []vals = []cur = nxtreturn ans该算法通过cur/nxt。

2025-07-03 20:44:20 333

原创 二叉树题解——二叉树的直径【LeetCode】

*“直径”**指的是树中任意两个节点之间最长的路径长度;路径长度指的是边的数量,即经过的节点数 - 1。以node为根的子树的最大深度,核心是后序遍历。利用后序遍历,求出每个节点左、右子树深度,并尝试用L + R + 1更新最大路径节点数。✅ 通过每个节点作为路径“中间点”,记录“穿过该节点的最长路径”;✅ 所有这样的路径中最长者就是二叉树的直径;✅ 最终减去 1 就得到边数形式的直径长度。self.ans = 1 # 初始化结果为 1# 访问到空节点了,返回 0return -1。

2025-07-03 09:45:53 519

原创 双指针题解——反转字符串【LeetCode】

使用双指针从两端向中间逐步交换字符,实现原地反转。✅ 原地操作,空间效率高;✅ 每次只交换两个字符,简单直接;✅ 适用于字符串、数组等序列类型的反转模板。""""""left = 0left += 1right -= 1return s本算法通过双指针原地交换的方式,在 O(n) 时间、O(1) 空间内高效完成字符串反转,是序列处理中最经典、通用的技巧之一。

2025-07-02 09:35:27 199

原创 二叉树题解——对称二叉树【LeetCode】

dfs(p, q)比较两个节点p和q代表的子树是否对称。将树的“对称性”问题转化为“两个子树是否镜像”的判断,并使用递归双指针同步对比两棵子树的结构与值。✅ 双指针pq分别走向左、右子树的“对称位置”;✅ 比较顺序是 “左对右,右对左”,从而形成“镜像”判定;✅ 本质是结构和数值都一致的镜像匹配问题。if not (p or q): # 都是空节点if not (p and q): # 只有一个为空,不对称if p.val!= q.val: # 值不等,不对称# 递归判断:左对右,右对左。

2025-07-02 00:30:00 418

原创 二叉树题解——翻转二叉树【LeetCode】

整个算法从叶子节点向上,逐步完成左右子树的交换。每个节点都做“翻转自己的左右子树”这一件事,由递归统一调度,最终完成整棵树的翻转。这段代码的核心思想是:使用后序遍历的递归方式,自底向上交换每个节点的左右子树。✅ 后序遍历是关键:必须先处理完子树,再交换;✅ 每个节点只处理一次,处理内容就是“递归子树 + 左右互换”;✅ 属于结构清晰、直觉明确的树形递归模板。return root # 如果当前节点为空,直接返回# 递归翻转左子树和右子树# 交换左右子树# 返回翻转后的当前节点。

2025-07-02 00:15:00 249

原创 二叉树题解——二叉树的最大深度【LeetCode】两种方法实现

最大深度是指从根节点到最远叶子节点的最长路径上的节点数。递归地计算左右子树的最大深度,然后返回“更深的一侧 + 当前层”作为整体深度。这是一个典型的后序遍历问题,因为只有等左右子树处理完毕后,才能计算当前节点的高度。这两个递归实现都通过“后序遍历 + 层高累计”的方式求解二叉树最大深度。一个精简直接、一个易读明确,本质相同,都是标准的二叉树深度问题递归写法,时间和空间复杂度均为线性级别。每一轮 while 循环处理一层节点,处理完后就将深度 +1,最终的层数就是最大深度。

2025-07-01 13:27:18 939

原创 二叉树题解——二叉树的中序遍历【LeetCode】颜色标记法

通过颜色状态模拟递归流程,显式管理“节点处理的阶段”,从而完成中序遍历。相比传统的栈模拟或统一写法,它具有以下优势:✅ 清晰区分每个节点的处理阶段(未访问 / 待访问);✅ 适用于中序 / 前序 / 后序统一写法,仅需调整压栈顺序;✅ 可用于复杂场景(如前序+后序同时记录、构建表达式树等)。WHITE, GRAY = 0, 1 # 定义颜色常量res = [] # 结果列表stack = [(WHITE, root)] # 初始化栈,根节点以 WHITE 状态压入。

2025-07-01 13:18:16 374

原创 二叉树题解——二叉树的中序遍历【LeetCode】统一写法版本

将访问节点值与处理子节点的过程“解耦”,用类型判断区分是否“已展开”。✅ 借助栈顺序控制访问流程;✅ 用来判断当前栈元素是否是“待处理节点”;✅ 中序遍历通过压入[右子树, 当前值, 左子树]的顺序来模拟递归。这种技巧具有很高的统一性和可拓展性,适用于中序、前序、后序的迭代实现,只需要改变压栈顺序。stack, rst = [root], [] # 初始化栈和结果列表i = stack.pop() # 弹出栈顶元素# 按照中序遍历的顺序,将右子节点、节点值、左子节点依次压入栈。

2025-07-01 13:18:03 650

原创 cur.next.val == val 中的 .val 是什么意思?

是访问下一个链表节点中的数值,.val是链表节点类ListNode中的属性,不能省略。

2025-07-01 03:00:00 251

原创 链表题解——移除链表元素【LeetCode】

引入虚拟头节点,统一处理所有删除逻辑,避免特判头节点。✅ 哨兵节点消除了对头节点是否是目标值的特殊处理;✅ 通过操作cur.next删除下一个节点,避免在删除操作中提前丢失遍历控制;

2025-06-30 22:40:41 445

原创 链表题解——设计链表【LeetCode】

哨兵节点 + size记录 + 链式结构 + O(n)遍历插删是这类链表题目的核心构建思路。✅ 哨兵节点(dummy node)避免对头节点操作的特殊判断;✅ 使用size记录链表长度,快速判断边界合法性;✅ 所有插入、删除都通过“遍历到前一节点”来操作;✅ 遵循单链表结构特性,无随机访问能力。(版本一)单链表法return -1returnreturn这段代码通过使用哨兵头节点 + 封装常用操作 + 控制链表长度,使得链表插入、删除操作逻辑清晰简洁,是典型的单链表构建方式。

2025-06-30 22:33:10 833

原创 链表题解——两两交换链表中的节点【LeetCode】

将问题局部化:只处理当前两个节点,其余部分交给递归;天然递归拼接结构:每一对交换完成后,通过递归返回值自然连接;思路简洁清晰:每次递归都只处理“两两交换”这个最小问题单元。“局部交换 + 递归合并”。# 递归版本if head is None or head.next is None: # 递归边界return head # 不足两个节点,无需交换node1.next = self.swapPairs(node3) # 1 指向递归返回的链表头。

2025-06-30 22:29:25 912

原创 链表题解——删除链表的倒数第 N 个结点【LeetCode】

✅双指针+间距:让快指针先走n+1步,再同步前进,从而让慢指针精确指向倒数第n个节点的前一个节点。✅虚拟头节点:极大地简化了链表头节点被删除时的边界处理。✅一次遍历完成删除操作:只需一趟扫描,不需要先获取链表长度,节省效率。# 创建一个虚拟节点,并将其下一个指针设置为链表的头部# 创建两个指针,慢指针和快指针,并将它们初始化为虚拟节点# 快指针比慢指针快 n+1 步# 移动两个指针,直到快速指针到达链表的末尾# 通过更新第 (n-1) 个节点的 next 指针删除第 n 个节点。

2025-06-29 15:54:45 399

原创 链表题解——环形链表 II【LeetCode】

该算法通过快慢指针的相遇与数学性质,在线性时间和常数空间下找出链表环的入口节点,核心在于“环形追赶+数学推导。

2025-06-29 15:38:02 867

原创 链表题解——回文链表【LeetCode】

该算法巧妙地结合了快慢指针、链表反转和双指针比较,在线性时间和常数空间下高效判断链表是否为回文。核心在于利用快慢指针找到中点 + 原地反转链表来规避额外空间使用。方式是否可行空间复杂度是否破坏链表结构是否高效整体反转 + 比较原链表❌ 不可行O(n) or 破坏原链表会破坏结构否复制一份 + 反转副本 + 比较✅ 可行O(n)不破坏否当前解法(快慢指针+反转后半段)✅ 优秀解O(1)前半结构保留是 ✔️。

2025-06-29 11:16:13 722

原创 数据库左连接与右连接的区别

特性LEFT JOINRIGHT JOIN保留数据的主表左表(FROM 后面的表)右表(JOIN 后面的表)未匹配记录的处理右表字段为 NULL左表字段为 NULL数据完整性关注点关注左表中的全部数据关注右表中的全部数据常见用途示例获取所有玩家及其充值信息(即使没充值)获取所有充值记录及其玩家信息(即使玩家被删除)

2025-06-28 23:38:00 310

原创 Linux软连接和硬连接

类型软连接(Symbolic Link)硬连接(Hard Link)本质类似于 Windows 的“快捷方式”是文件的另一个名字(指向同一个 inode)存储方式独立文件,存储目标文件的路径直接指向原文件的 inode(数据块)跨分区支持✅ 支持(路径可跨磁盘)❌ 不支持(必须同一文件系统)原文件删除软连接失效(变成“死链”)硬连接仍可访问文件数据文件属性权限始终是 (实际权限依赖原文件)权限与原文件相同文件系统结构示例:3. 命令对比 操作软连接硬连接创建查看显示链接路

2025-06-28 23:36:44 323

原创 链表题解——两数相加【LeetCode】

该实现采用逐位处理两个链表,并考虑。

2025-06-27 16:45:36 486

原创 矩阵题解——螺旋矩阵 II【LeetCode】

【代码】【无标题】

2025-06-27 00:45:00 252

原创 矩阵题解——搜索二维矩阵 II【LeetCode】

1.1 核心思想

2025-06-27 00:45:00 372

原创 矩阵题解——旋转图像【LeetCode】

【代码】矩阵题解——旋转图像【LeetCode】

2025-06-26 00:45:00 335

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除