MrHe

MrHe

河南科技大学-软件工程

About this publication

欢迎来到小何的博客,25届本科毕业生,河南科技大学软件工程专业,主攻Java,对python、vue、uniapp、大模型等技术都有涉及。

字典树和后缀数组

14.2 字典树的应用算法设计 字典树,也叫Trie树或者前缀树,顾名思义,它就是一种专门用来处理字符串前缀的树形结构。每个节点代表一个字符,从根节点到任意一个节点的路径,就构成了一个字符串。它的核心思想就是用空间换时间,利用字符串的公共前缀来降低查询时间的开销。 14.2.1 实现Trie(前缀树) 问题描述 实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。 Trie() 初始化前缀树对象。 void insert(String...

Date: |Estimated Reading Time: 9 min|Author: MrHe

树状数组( Binary Indexed Tree)

树状数组(Fenwick Tree / Binary Indexed Tree)这个东西。这玩意儿听起来挺唬人,但本质上就是个用数组模拟树形结构的工具,专门用来解决一类问题:频繁的单点更新和区间查询。如果我们用普通数组,更新是 O(1),但查区间和就是 O(N);用前缀和数组,查区间和是 O(1),但你更新一个点,后面所有的前缀和都得改,又是 O(N)。两边都不讨好。树状数组就把这两个操作都干到了 O(logN),一下就平衡了。 废话不多说,咱们从题入手,看看这东西到底怎么用,思路是怎么一步步升...

Date: |Estimated Reading Time: 10 min|Author: MrHe

线段树-树形结构

线段树,顾名思义,就是用来处理区间或线段问题的树形结构。它能高效地解决一类问题:对一个数组进行频繁的区间查询和元素更新。如果你看到一个问题,反复地问你“从L到R这个范围内的xx是什么?”或者“把L到R这个范围内的数都改成xx”,那线札树可能就是你的答案。 它的核心思想就是“分治”。把一个大区间,一分为二,变成两个小区间,直到每个区间只包含一个元素。这样,一个长度为N的数组,就对应了一棵满二叉树(或近似满二叉树),树的深度是 O(logN)。每一次查询和更新,我们都只需要沿着树的一条路径走到底,所...

Date: |Estimated Reading Time: 9 min|Author: MrHe

优先队列PriorityQueue

很多时候,我们处理数据不只是简单地存进去、取出来,而是希望每次取出的都是当前这批数据里"最"牛的那个,比如最大、最小、最重要等等。普通队列是先进先出,栈是后进先出,都满足不了这个需求。这时候,优先队列就登场了。 你可以把它想象成一个VIP候机室,不管你什么时候来的,只要你的"优先级"最高(比如是头等舱、白金会员),你就能最先登机。在算法里,这个"优先级"通常就是元素的大小。 Java里 PriorityQueue 就是它的标准实现,底层是一棵二叉堆(小顶堆)。这意味着,它能用 O(logN) 的...

Date: |Estimated Reading Time: 14 min|Author: MrHe

并查集(Disjoint Set Union, DSU)

并查集(Disjoint Set Union, DSU)是一种非常有用的数据结构,主要用来处理一些不相交集合的合并及查询问题。听起来很抽象,但其实核心就两个操作: find:查找一个元素属于哪个集合(通常通过返回该集合的代表元素,也就是根节点)。 union:将两个元素所在的集合合并成一个集合。 为了让find操作更快,我们通常会加上一个“路径压缩”的优化。为了让合并后的树结构更平衡,会加上“按秩合并”或“按大小合并”的优化。 10.2 一维并查集的应用算法设计 10.2.1 以图判树...

Date: |Estimated Reading Time: 12 min|Author: MrHe

经典的图论问题

K 站中转内最便宜的航班 (LeetCode 787) 问题描述 有 n 个城市通过一些航班连接。给你一个数组 flights ,其中 flights[i] = [from_i, to_i, price_i] ,表示该航班将会从城市 from_i 前往 to_i ,价格为 price_i 。 现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,你的任务是找到出一条最多经过 k 次中转的路线,使得从 src 到 dst 的价格最便宜,并返回该价格。 如果不存在这样的路线,则输出 -1...

Date: |Estimated Reading Time: 6 min|Author: MrHe

递归数据结构

啥叫递归数据结构?你看链表,一个节点后面跟着另一个节点,这不就是自己套自己嘛。你看二叉树,一个根节点下面连着左子树、右子树,子树本身又是二叉树。对付这种结构,递归就是最顺手的兵器。 16.2.1 从链表中移除结点 问题描述: 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。 示例: 输入: head = [1,2,6,3,4,5,6], val = 6 输出: [1,2,3,4,5] 思路分析: 这题...

Date: |Estimated Reading Time: 18 min|Author: MrHe

顺序列举、组合列举、排列列举

15.2 顺序列举的算法设计 这类问题通常是处理一个序列(比如数组、字符串),我们要找的是其中满足特定条件的、连续的一部分。 15.2.1 最大连续 1 的个数 题目:给定一个二进制数组 nums , 计算其中最大连续 1 的个数。 拿到这个题,第一反应是什么?找“连续的1”,那我就把所有可能的“连续段”都找出来,看看哪个段里的1最多。 解法一:暴力枚举所有子数组 O(N²) 最无脑的办法,就是两层循环。第一层循环i定开头,第二层循环j定结尾,然后去数[i...j]这个区间里是不是全是1。 p...

Date: |Estimated Reading Time: 23 min|Author: MrHe

跳跃问题、迷宫问题和设计问题

好的,今天我们来聊一聊算法题里非常经典的三大类问题:跳跃问题、迷宫问题和设计问题。这几类问题在面试里出镜率极高,而且花样繁多,但万变不离其宗。咱们就用左老师的风格,从最暴力的方法开始,一步步把思路理清,看看怎么把一个问题分析透彻,最终找到最优解。 第 23 章 跳跃问题 跳跃问题,本质上是在一个一维数组上移动,问你能否到达、最少几步到达,或者有多少种方式到达。这类问题的核心,在于定义清楚“状态”。我们通常会定义 dp[i] 表示从位置 i 出发,能得到什么样的答案。 23.2.1 跳跃游戏 I...

Date: |Estimated Reading Time: 24 min|Author: MrHe

堆(优先队列)

写了这么久代码,我发现很多数据结构本质上都是为了解决特定场景下的效率问题。数组增删慢、查询快;链表增删快、查询慢。那如果我有个需求:动态地、快速地找到一群数据里的最大值或最小值,该用啥? 你可能会说,用个数组存着,每次找最大值就遍历一遍,O(N) 嘛。可以,但如果这个操作要进行一万次呢?效率太低了。如果我每次插入新数据后都排序呢?那插入一个数就得 O(N*logN),更慢。 这时候,堆(Heap)就该登场了。它就是为了这个场景而生的。 一、掰开揉碎,啥是堆? 说白了,堆就是一个特殊的树。但你别被...

Date: |Estimated Reading Time: 4 min|Author: MrHe

数学优化算法题

给定一个整数 n,返回 n! 结果尾数中零的数量。 例子: 输入: 5 输出: 1 解释: 5! = 120, 尾数中有 1 个零. 解法一:暴力解,朴实无华 拿到这个题,我第一反应就是最简单的思路:先把 n 的阶乘算出来,然后看它末尾有几个 0。这思路没毛病,非常直接。 怎么算末尾有几个 0 呢?就是一个数不停地除以 10,直到不能整除为止,看总共除了多少次。 来,上代码。 import java.math.BigInteger; class Solution1 { public ...

Date: |Estimated Reading Time: 3 min|Author: MrHe

最小生成树(Minimum Spanning Tree, MST)

这玩意儿听起来挺唬人,但其实思想特别朴素。想象一下,现在有几个村庄,你要负责修路把它们都连起来,并且想花最少的钱。每条备选的路都有一个造价。你怎么设计这个路网,才能保证所有村庄都能互相到达,并且总造价最低? 这就是最小生成树。给你一张带权重的无向图,找一棵能连接所有顶点的树,并且这棵树所有边的权重之和最小。 扯远了,拉回来。搞定这个问题,有两个经典的“骚操作”,一个叫Kruskal,一个叫Prim。这两个都是贪心算法,但贪心的角度不太一样。今天咱们把这俩都盘明白了。 准备工作:图怎么表示? 在撸...

Date: |Estimated Reading Time: 5 min|Author: MrHe

单调队列问题

今天聊个有意思的结构:单调队列。 别被这名字吓到,听着好像挺学术,其实就是个双端队列(Deque),但咱们给它立了个规矩,让它里面的元素满足单调性。就这么简单。 这玩意儿有啥用?它专门解决一类问题,最经典的就是“滑动窗口最大值”。为了把这个结构讲透,咱们就拿这个问题开刀。 题目:滑动窗口最大值 (LeetCode 239) 给你一个整数数组 nums,有一个大小为 k 的滑动窗口,从数组的最左侧移动到最右侧。你只能看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回一个数组,包含每个...

Date: |Estimated Reading Time: 6 min|Author: MrHe

解数独(Sudoku)

别小看这玩意儿,好像就是填格子,但里面的门道可不少。一个题,能玩出好几种花样,从新手小白到算法老鸟,都能在里面找到自己的乐趣和挑战。今天,我就带你走一遍我的心路历程,看看怎么从最笨的方法,一步步优化到让面试官都眼前一亮的程度。 题目要求很简单:给你一个9x9的数独棋盘,里面有些数字已经填好了,有些是空的(用 . 表示),让你把空的地方填满,让整个数独成立。 规则大家都懂: 每一行,数字1-9都得出现一次,不能重复。 每一列,数字1-9都得出现一次,不能重复。 每一个3x3的小九宫格里,数字...

Date: |Estimated Reading Time: 5 min|Author: MrHe

如何玩转数据流

今天聊一个在面试里出镜率极高,也特别能体现算法思维的话题——数据流。 啥是数据流?你可以想象成一个永无止境的传送带,上面源源不断地送来数据。比如,服务器的访问日志、股票市场的实时报价、传感器传回的温度读数。这些数据的特点是: 量巨大,甚至可能是无限的。 你没法一次性拿到所有数据,它们是一个一个来的。 内存有限,你不可能把所有数据都存下来。 处理这种问题的算法,就叫数据流算法。它考验的是我们如何在有限的资源下,做到快速响应和计算。 今天,咱们就拿数据流里最经典的一道题开刀:数据流中的中位...

Date: |Estimated Reading Time: 3 min|Author: MrHe

博弈论算法优化

有一堆石子,共 n 个。你和另一个人轮流从堆里拿石子,每次可以拿 1 个、2 个或 3 个。拿到最后一个石子的人算赢。假设你先手,并且两个人都足够聪明,请问你是否能赢? 这种“两个人足够聪明”的题,就是典型的博弈论。所谓“足够聪明”,意思就是每个人在轮到自己时,都会选择最优策略,绝不失误。 解法一:暴力递归,一力降十会 一看到这题,我的第一反应通常是:我能不能赢,取决于我走了某一步之后,对方是不是必输。 这是博弈论的核心思想:我赢,当且仅当我能走到一个让对手必输的局面。 这句话有点套娃的感觉,...

Date: |Estimated Reading Time: 3 min|Author: MrHe

滚动哈希:字符串匹配的艺术

搞算法的,谁还没被字符串匹配问题捶过?给你一个长文本串 T 和一个模式串 P,让你找出 P 在 T 中所有出现的位置。这问题太经典了,经典到面试官闭着眼都能问出来。 比如,T = "abababa",P = "aba",那 P 在 T 中的起始位置就是 0, 2, 4。 拿到这种题,脑子里第一反应是啥?别想太多,先上暴力,这是对题目最基本的尊重。 解法一:简单粗暴的暴力匹配 这个思路最直接,也最符合人类的直觉。 我就把 P 当成一个尺子,从 T 的开头开始,一位一位地往后对。 把 P 对准 T...

Date: |Estimated Reading Time: 4 min|Author: MrHe

字符串匹配问题

这问题太经典了,基本上是面试必考,笔试常见。问题很简单:给你一个字符串 s(通常叫主串),再给你一个字符串 p(叫模式串),让你在 s 里面找到 p 第一次出现的位置,找不到就返回 -1。 比如 s = "ababcabcacbab",p = "abcac",p 在 s 的第 5 个位置(下标为 4)出现了,咱么就返回 4。如果 p = "abx",在 s 里找不到,就返回 -1。 拿到这种题,别慌,先上最朴素、最符合直觉的解法。 解法一:暴力中的暴力,简单又粗暴 啥是暴力解法?就是完全不动脑子...

Date: |Estimated Reading Time: 4 min|Author: MrHe

图的最短路问题

聊到图论,最短路是个绕不开的坎。别看它名字简单,里面的门道可不少。不管是面试还是实际应用(比如地图导航、网络路由),这玩意儿都极其重要。 很多时候我们看到一个算法题,如果没有思路,第一反应是啥?暴力枚举呗。那最短路的暴力解法是啥?把从起点到终点的所有可能路径都列出来,然后一个个算它们的权重和,最后取个最小值。 想法很简单,但你稍微画个图就知道,一个稍微复杂点的图,路径的数量就是指数级爆炸,这谁顶得住?所以,暴力解法咱们心里有数就行了,它只能作为思考的起点,根本没法写。 今天,咱们就从正经的解法开...

Date: |Estimated Reading Time: 5 min|Author: MrHe

哈希函数算法

一提到“哈希”,很多人第一反应就是 HashMap。没错,但 HashMap 只是哈希思想的一种顶级应用。今天,我想带你回到原点,看看哈希这个思想是怎么一步步演化,并最终在计算机科学中变得如此重要的。这中间的每一步思维提升,都特别有意思。 场景一:最简单的需求,判断一个数在不在 假设现在我给你 1 亿个 int 类型的数,然后我再给你一个数,让你告诉我这个数在不在这 1 亿个数里。 解法一:暴力,永远的神 我的第一反应,也是最朴素的反应,就是遍历。 public boolean contains...

Date: |Estimated Reading Time: 2 min|Author: MrHe