IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

算法

共 589 篇文章

IT 2026-06-03 09:03:24 / 累计浏览 10

Four Levels Of Customer Understanding

用户理解不能仅依赖表面反馈,需通过多层次三角验证揭示真实动机。Hannah Shamji提出的四层理解框架指出:第一层“用户所说”易收集但主观且常不可靠;第二层“用户所想所感”需通过访谈深入,但仍受记忆偏差影响;第三层“用户所做”通过行为数据分析实际操作;第四层“用户为何这样做”则需观察工作流程并建立信任关系以探求根源动机。研究表明直接提问效果有限,因用户常无意识美化或简化表达,且语言描述如“可能”“大概”等存在显著理解偏差。实践中应避免单纯验证既有假设,转而通过无干扰观察记录鼠标轨迹、停留时间及微表情等非语言信号,并借助情绪轮工具细化情感分析。最终需建立可持续的用户接触机制(如定期观察、跨部门共情会),将分散洞察转化为组织共识,超越“同理心表演”聚焦于问题诊断与动机溯源。

本机暂存
IT 2026-06-03 09:03:24 / 累计浏览 9

除法的意义

作者发现三年级女儿可可在掌握除法计算后仍无法理解其意义,表现为面对实际问题时无法将“装盒”场景与除法运算关联。通过实物操作(用token和碗模拟装鸡蛋)和逐步抽象化的引导,作者帮助孩子从具体行为中推导出除法的本质:连续减法的次数记录。例如通过“30个鸡蛋每10个装一盒”的实物操作过渡到用减法计算30-10-10-10=0并数次数,使孩子领悟除法符号的简化作用。进一步通过矩形图示解释乘除法的交换关系(8×10与10×8对应图形旋转),并拆解96÷8为80÷8+16÷8的分步计算,最终让孩子将除法竖式与实际分组过程对应起来。整个过程强调数学符号的具象化意义——符号是帮助思维的工具,但需先理解其代表的实际逻辑。通过一小时的具体演绎,孩子初步建立起除法作为“重复减法”的操作意义与乘除法间的互逆关联认知。

本机暂存
IT 2026-06-03 09:03:24 / 累计浏览 11

如何手搓一辆公路车

本文详细记录了一名程序员出于兴趣,从零开始手工组装一辆碳纤维公路车的完整过程。作者基于前一辆车(迪卡侬Triban RC500)的使用体验进行迭代,核心目标是打造一辆几何舒适、以耐用性为主的机械变速公路车。选件阶段,作者通过bikeinsights等工具对比车架几何,最终选择了与旧车STR值相近的Seka Spear车架,并针对性地调整了把立长度(110mm)、曲柄长度(165mm)等参数以优化人机工程。套件选择以兼容性和学习成本为优先,采用了Shimano 105机械变速套件,但将中轴、飞轮、链条等关键传动部件升级至更高等级以提升耐用性。 装车过程耗时约一周,遭遇了多项挑战:一体把内走线穿管(四根硬质线管)极为困难;车架为电变设计,导致机械前拨安装需要自制垫片解决兼容性问题;还遇到后碟片尺寸不匹配、夹器螺丝过短等零件问题。作者通过打磨线管出口、魔改垫片、使用穿线引导器及清洁剂处理碟片油污等方法逐一解决。整个安装遵循从内到外的顺序,强调了认真阅读说明书、使用扭力扳手、工具定点存放的重要性。 最终完成的车辆在轻量化、滤震性和换挡精准度上相比旧车有显著提升,验证了作者前期配置选择的正确性。作者总结认为,自组公路车过程复杂且需应对大量细节问题,普通用户更适合购买整车或请专业车店组装;但对于爱好者而言,从想法到实机的过程带来了巨大成就感。

本机暂存
IT 2026-06-03 09:03:24 / 累计浏览 13

第五章:共识算法

共识算法旨在解决分布式系统在部分节点故障或网络异常时,如何让存活节点就系统状态达成一致的根本问题。它不仅是实现状态机复制的理论基础,也是 Leader 选举、原子广播和集群配置变更等核心功能的驱动力。不同于两阶段提交协议的阻塞特性,共识算法追求的是在容错前提下达成一致,即使少数节点失效也能保证系统持续推进。 其核心目标是在不可靠的异步网络中,使一组进程就某个提议值达成唯一且不可逆的协定。这一机制广泛应用于确保主从复制的正确性、维护分布式数据库的副本一致、实现分布式事务的原子性以及决定事件的全局顺序等场景。 算法的复杂性主要源于节点崩溃、网络延迟或分区、拜占庭故障等挑战。从概念上必须区分“共识”与“一致性”:一致性描述数据副本的状态或外部视图的一致,而共识是达成该状态所采用的一种内部协调协议,是实现强一致性的重要技术手段。

本机暂存
IT 2026-06-03 09:03:24 / 累计浏览 9

对数和自然对数的底

对数概念的发明源于天文学中对大数乘除法的简化需求,特别是在通过三角视差法测量天文距离时。由于日地距离已很遥远,测量更远的恒星需要极高的精度,计算误差会显著影响结果。约翰·纳皮尔在没有幂概念的情况下,通过三角公式的启发,从几何意义出发发明了对数。其核心思路是构造一个等比数列,使真数的乘法运算转换为对应等差数列的加减运算。他选择了一个非常接近1的公比(约为0.9999999),这使得等比数列的递推可以通过简单的移位和减法实现,极大方便了手算。在当时以十的七次方为半径的三角函数表背景下,这个选择使得对数表的底数近似为(1+1/10^7)^(10^7),其极限即为自然常数e。因此,以e为底的对数之所以被称为自然对数,并非源于纳皮尔的本意,而是因为e是通过对数运算的自然数学构造过程(令公比的指数趋于无穷)而产生的必然结果。

本机暂存
IT 2026-06-03 09:03:24 / 累计浏览 8

一个简单的 A star 寻路算法实现

这篇讲的是一个极简A*寻路算法的实现,作者从实用角度出发,重新设计了一套C语言接口,核心特点是与地图数据结构完全解耦,方便移植到不同场景。 实现上最巧妙的是用单向链表替代了传统A*中复杂的优先队列,同时把所有寻路数据压进一块平坦内存,这样既避免了算法执行中的内存分配,又天然兼容多线程环境。底层数据结构是一个闭散列哈希表,作者用一个自增的version值巧妙实现了O(1)复杂度的表重置,大幅降低重复寻路时的初始化开销。 考虑到实际地图规模,算法内置了安全阀:当哈希表使用率超过一半时自动中止,但会返回已找到的离目标最近的中途点,用户可多次调用拼接完整路径。作者还贴心地提供了可视化函数,能将哈希表内部状态输出为灰度图,方便调试。 虽然代码刚写好还未充分测试,但作者追求的“接口简单、数据结构通用、内存开销固定”的设计目标清晰明确,适合那些需要轻量、易集成寻路功能的项目。

本机暂存
IT 2026-06-03 09:03:24 / 累计浏览 9

个人投资的最佳实践 - 读《不落俗套的成功》

本文基于耶鲁大学投资总监大卫·F·斯文森的著作《不落俗套的成功》,探讨了个人投资者可借鉴的两大核心实践。作者结合自身经历,首先强调了资产配置与再平衡的关键性。书中提出将资产分散配置于国内股票、国外股票、房地产及不同债券等六大类,而实践中可根据可得标的(如A股、港股、债券基金等)进行调整,关键在于避免任何单一资产占比过高(如超过30%)。作者以自身追高导致亏损的教训,说明应坚持定期再平衡:在资产涨幅过大时卖出、在跌幅过大时补仓,以维持目标比例,这虽反人性但能有效控制风险。 其次,文章深入剖析了高费率基金的长期弊端。通过数十年数据及作者持有的私募基金实际案例(显示费后收益显著低于表面收益),揭示管理费与提成如何大幅侵蚀收益,尤其在市场波动中导致投资者实质亏损。基于此,作者转向低费率指数基金,并投资于少数理解其商业模式的个股。总体而言,该书通过数据论证了分散配置与规避高费率对个人投资成功的重要性。

本机暂存
IT 2026-06-03 09:03:24 / 累计浏览 7

CSPJ 教学总结:深度优先搜索(DFS)

深度优先搜索(DFS)是算法学习的基础,其核心是递归实现,需通过参数传递保存搜索状态。标准DFS模版包含终止条件、合法选项枚举、状态标记与恢复等关键步骤。实际应用中需关注递归深度对栈空间的占用,竞赛环境通常限制栈大小为8-16MB,建议递归深度控制在1万层以内以防溢出。 通过多类典型题目可深入理解DFS应用:八皇后问题通过逐行放置并检查斜线冲突实现经典搜索;选数问题采用递归枚举组合并判断素数;Lake Counting与迷宫问题利用DFS进行连通区域标记与路径探索;PERKET问题通过DFS枚举所有选菜组合计算酸度甜度差;黑白棋问题需结合多重剪枝策略(行列计数、连续检查、唯一性验证)优化搜索;自然数拆分问题则通过保证数列非递减来避免重复解。这些案例展示了DFS在组合枚举、图遍历、约束满足等场景中的灵活应用,体现了状态保存、剪枝优化等关键思想。

本机暂存
IT 2026-06-03 09:03:24 / 累计浏览 5

CSPJ 教学总结:树状数组

树状数组(Binary Indexed Tree)是一种用于高效处理动态序列单点更新与区间求和问题的数据结构。其核心思想是利用二进制表示和 lowbit 操作,构建一个辅助数组,将前缀和查询与单点更新的时间复杂度均优化至 O(log N)。文章从暴力解法的瓶颈出发,逐步剖析 lowbit 函数的原理与实现、树状数组的结构定义、求和与更新操作的具体步骤,并说明了如何通过前缀和数组将初始化复杂度降至 O(N)。进一步,文章阐述了每个树状数组元素所管辖的区间范围及其在更新与查询过程中的变化规律。此外,还介绍了树状数组与差分数组结合以处理区间更新问题、二维树状数组的扩展,以及利用树状数组求解逆序对数量的应用场景与离散化处理技巧。

本机暂存
IT 2026-06-03 09:03:24 / 累计浏览 11

GESP 202506 5级真题「奖品兑换」题解

这篇题解讲的是 GESP 2025 年 6 月五级的一道题目“奖品兑换”。题目要求用两种面值的兑换券兑换奖品,求能兑换的最大数量,数据规模高达 10^9,直接暴力枚举肯定超时,而想设计一个万无一失的贪心策略又很困难。 作者的核心解法是“二分答案+判定”。关键思路在于:兑换券数量越多,所需的另一种券就越多,满足单调性,因此可以对最大兑换数进行二分搜索。对于每一个待检验的答案 k,先按“全都用大面值券兑换”的方式计算,如果小面值券超额了,就逐步将部分兑换方案切换为使用小面值券,通过计算需要切换的次数(涉及向上取整)来判断是否在总券数内可行。 整道题综合考查了二分搜索、数学推导(包括向上取整的代码写法)以及对数据范围的敏感度。题目设计有区分度:没想到二分的同学用贪心或暴力也能拿到部分分数,而想出最优解则能全面锻炼算法思维。代码实现时还需要注意用 `long long` 防止溢出。

本机暂存
IT 2026-06-03 09:03:23 / 累计浏览 9

算法模式:前缀和

前缀和是一种高效的数组预处理技术,用于解决区间和查询问题。其核心思想是预先计算数列前n项的累计和,生成一个前缀和数组,使得任意区间的和可以通过简单的减法运算快速获得。这种方法将每次查询的时间复杂度从O(n)降低到O(1),代价是需要额外的O(n)空间存储前缀和。在具体应用中,例如LeetCode 303题“区域和检索 - 数组不可变”,要求对给定数组频繁执行区间求和操作。通过初始化时构建前缀和数组(其中prefix[0]为0,prefix[i]表示原数组前i-1项的和),sumRange(left, right)方法可以直接返回prefix[right+1] - prefix[left],避免了重复遍历数组的开销。该模式特别适合数据不可变且查询密集的场景,是优化动态规划或滑动窗口等问题的常见辅助手段。掌握前缀和有助于提升算法效率,尤其在处理大数据集或实时查询时,能显著减少计算成本。

本机暂存
IT 2026-06-03 09:03:23 / 累计浏览 11

算法模式:并查集

并查集是一种用于解决动态连通性问题的数据结构,能够高效管理节点间的连接关系并快速判断任意两点是否属于同一连通分量。其核心操作包括`union`(合并两个节点所属的集合)和`connected`(查询两个节点是否连通)。初始化时每个节点自成一组,通过`parent`数组记录节点的父节点,最终形成树状结构。 判断连通性时需向上查找各自根节点并比较是否相同。为提升查询效率,可应用路径压缩技术:在查找根节点过程中,将路径上所有节点直接指向根节点,从而大幅降低后续操作的时间复杂度。文章通过图示和Java代码示例展示了并查集的基本实现,包括查找、合并、连通分量计数等功能,体现了其在处理动态集合合并与连通性查询场景下的实用性。

本机暂存
IT 2026-06-03 09:03:23 / 累计浏览 10

算法模式:子集

在上一篇文章 算法模式:回溯 介绍一种“一步三回头”、“落棋有悔”的算法模式:回溯。本篇文章,介绍一种无需“一步三回头”,无需“落棋有悔”也可以解决排列组合问题的算法模式:子集。

子集

超级多的编程面试问题都会涉及到排列和组合问题。一般都是使用回溯来解决该类问题,回溯法属于 深度优先搜索。子集问题模式讲的是用 广度优先搜索 来处理这些问题。子集模式适用于子集与全排列。下面分别介绍:

处理子集问题

举例来说明一下这个模式:

给一组数字 [1, 5, 3]

  1. 我们从空集开始:[[]]

  2. 把第一个数 1,加到之前已经存在的集合中:[[], [1]];

  3. 把第二个数 5,加到之前的集合中得到:[[], [1], [5], [1,5]];

  4. 再加第三个数 3,则有:[[], [1], [5], [1,5], [3], [1,3], [5,3], [1,5,3]].

如果原有集合中存在重复元素,那么就需要针对这种情况特殊处理一下。流程如下:

给一组数字 [5, 1, 5]

  1. 先对原有集合进行排序: [1, 5, 3]

  2. 从空集开始:[[]]

  3. 把第一个数 1,加到之前已经存在的集合中:[[], [1]];

  4. 把第二个数 5,加到之前的集合中得到:[[], [1], [5], [1,5]];

  5. 处理第三个数,也是 5 时需要注意:

    1. 如果还是按照上述方案处理,那么就会得到如下结果: [[], [1], [5], [1,5], [5], [1, 5], [5, 5], [1,5, 5]]。这里出现了重复子集: [5], [1, 5]。该方案不通过,❌

    2. 观察最后生成的所有子集与重复的子集,会发现重复的子集,在处理第二个数时,已经处理过 [], [1],如果再次处理 5,那么就会出现重复。所以,只需要处理在处理上一个相同的数时新增加的子集即可。上一个相同数新增的子集是 [5], [1,5],只需要在这些子集后面增加当前数字即可。这样最后的子集就是:[[], [1], [5], [1,5], [5, 5], [1,5, 5]]。方案通过 ✅

本机暂存
IT 2026-06-03 09:03:23 / 累计浏览 10

IP匹配的一些小tips

文章分享了在数据分析中进行IP匹配的实用技巧。针对基础匹配,可使用`IN`列表或`LIKE`语句处理单个IP或C段地址,但面对如`/22`、`/19`等较大CIDR网段时,逐条匹配写法繁琐且性能不佳。推荐的高效方案有两种:其一是将IP地址转换为整数,同时计算出网段对应的起止整数范围,通过整数区间的`BETWEEN`判断进行匹配,这种方法性能最优,适合大规模数据;其二是组合使用`LIKE`与数值范围判断,在网段数量有限时是一种折衷方案。此外,文章提供了一个Python脚本示例,该脚本能读取CIDR列表,合并重叠网段,并自动生成适用于Hive的整数区间匹配SQL条件,大大简化了预处理工作。整体内容聚焦于解决实际场景中的IP网段匹配效率问题。

本机暂存
IT 2026-06-03 09:03:23 / 累计浏览 10

几种通过 FFmpeg 无损压缩视频的方法

本文针对视频文件体积过大问题,介绍了几种基于 FFmpeg 工具进行有效压缩的技术方法。核心思路是通过调整编码参数或改变文件属性来减小体积,同时尽量保持画质。主要方法包括:使用 CRF(恒定速率因子)参数,通过设置较低的数值(如18)在视觉无损的前提下控制画质与文件大小的平衡;通过命令直接更改文件的封装格式而不重新编码,实现便捷转换;通过降低视频分辨率来显著减少数据量,适用于画质要求不高的场景;通过降低视频比特率来压缩文件,在保持原始分辨率的同时减少体积;以及采用更高效的 HEVC (H.265) 编码格式,它相比传统 H.264 在同等画质下能生成更小的文件。每种方法均附有具体的命令示例和原理说明,用户可根据对画质、兼容性及处理速度的需求进行选择。

本机暂存
IT 2022-07-24 20:46:45 / 累计浏览 3,927

用邻接表实现无向图

这篇讲的是作者在游戏管道系统扩展中,如何用邻接表实现一个无向图数据结构。作者从原有的液体管道系统(采用类似树的固定数组存储)出发,面对电线网络等新需求——节点无方向且可多邻接,决定重新设计。核心思路是将节点id与边关系分离,便于模块化复用。具体实现上,每条边用32位紧凑表示(16位端点id对,小id在低位确保唯一性),并设计了一个巧妙的结构:在边数据中加入两个链表指针,分别指向两端点所属的边集合,从而支持高效遍历。 更精巧的是,作者进一步压缩了存储:通过将其中一端点的边集合连续排列,另一端以链表链接,并用“反转端点id”来标志链表结束(通常小id在前),最终每条边只需48位。文章以九宫格网格图为例,完整演示了如何从节点索引开始,逐步追踪并找出顶点5的全部四条邻接边。作者坦言这种无向图实现并非日常工作所需,但经过半天编码,能写出这样紧凑高效的结构让他颇为满意,其压缩方案甚至可能具有一定的原创性。

本机暂存
IT 2021-06-13 22:34:06 / 累计浏览 2,525

可靠通信的三条基本定理

这篇讲的是可靠通信背后必须遵循的三条基本定理,以及如何用它们指导系统设计。作者认为,广义的可靠通信必须满足不丢包、不重复、完整性这三个要求,而对应的解决方案分别是确认与重传、排队(串行化)、单点标记或自校验。文章澄清了一个常见误区:去重问题的根源在于操作需要排队,即使采用全局位图方案,对位图的操作本身也需排队,而像CAS这样的实现,其内部本质也是排队。 这些定理并非空谈,文章通过实例展示了其强大的解释力。例如,TCP的可靠性正是因为它遵循了这三条定理:序号机制实现了排队,超时重传机制兜底处理丢包,checksum则保证了数据完整性。再比如,在线商店的库存超卖问题,本质上是一个需要排队的去重问题;而订单与支付两大独立系统之间的数据一致,则依赖于定理一(确认与重传)来保证不丢包。 作者的核心观点是,实际问题千变万化,但可靠的系统设计必须回归到这三条基础定理上。它们提供了最根本的讨论框架和判断标准:符合定理的设计方案才是可靠的,否则就存在隐患。理解这些基础模型,是构建正确、健壮系统的理论前提。

本机暂存
IT 2021-05-28 23:02:42 / 累计浏览 2,443

你需要更多的思考时间

这篇文章分享了一位技术从业者通过每日安排固定思考时间,来提升工作效率和生活质量的个人实践。作者每天七点半起床,利用通勤的一个半小时用kindle阅读,并提前一小时到公司,但这段时间他并不急于

本机暂存
IT 2021-05-28 08:32:57 / 累计浏览 2,386

不变量及运算优化

这篇讲的是游戏引擎开发中一个看似简单却消耗10%以上CPU时间的性能坑。作者从实际Profiling结果出发,发现每帧重建渲染队列时,需要对每个可渲染物件的包围盒进行世界空间变换运算,而场景中大量静态物件的这类运算是重复的。 问题的根源在于输入数据量太大(40个float),直接用作缓存键并不现实。巧妙之处在于,作者利用数学库中矩阵已作为不变量拥有唯一ID这一现有设计,将世界空间矩阵的ID作为缓存键,大幅缩减了比较开销。最终,缓存能按“世界矩阵ID”匹配并直接复用上一帧计算好的所有子模型变换结果,避免了重复计算。这个优化思路透明地解决了问题,而无需对场景或资源系统进行大改。

本机暂存
IT 2021-05-27 07:54:29 / 累计浏览 2,704

一篇写给从未编程过的人的入门教程

这篇讲的是编程入门的“心理障碍”有多不必要。作者开篇就破除了“外行/内行”的标签,认为编程本质是每个人都熟悉的逻辑表达,他以自己半天学会PlantUML为例,强调学习曲线比想象中平缓。 为了让抽象概念落地,作者巧妙地用“17点回家如何在18点30分前让家人吃上饭”这个日常场景,类比了编程中的算法(解决步骤)、数据结构(书架/柜子的存储逻辑)和程序实体(做饭)。这种类比让“编程=算法+数据结构”的公式瞬间变得亲切可感。 文章的核心观点是,区分编程小白与专家的,并非代码本身,而是思考问题的周全性。作者通过对比两段“做饭”的伪代码——一个临时发现没油才去买,另一个提前检查缺漏并携带清单——生动说明了后者如何通过“检查”步骤让流程更可靠、高效。这引出了编程中“抽象”思维的关键价值:将重复步骤(洗菜、切菜、炒菜)封装成方法,使得程序能通过扩展“菜单”而非重复代码来处理复杂任务。 最终,作者将编程的复杂性落回到现实:入门简单,但写出考虑周全、高效且能应对需求变化的“好程序”却极具挑战。结尾那句关于“程序员最苦恼的是需求变化”的调侃,也让这篇技术入门文多了一份共鸣和幽默。

本机暂存