常见数据结构及算法

必须掌握的数据结构及算法

掌握数据结构是应用算法的基础,以下是一些核心结构及其典型应用场景:

  • 栈与队列 用于深度优先搜索、括号匹配;队列用于广度优先搜索、滑动窗口。

  • 哈希表 :提供O(1)时间的快速查找,常用于缓存(LRU)统计频率、快速判断元素是否存在(如两数之和)。

  • 堆(优先队列) :能快速获取最大或最小元素,常用于解决Top K问题 、求中位数等。

  • 二叉树 的遍历(前、中、后序)是基础;二叉搜索树 支持高效查找;字典树专门处理字符串前缀问题。

  • 并查集 :高效处理分组连通性问题(如朋友圈、岛屿数量变种)。

  • 前缀和与差分

    • 前缀和:用于快速计算数组某个区间的和。

    • 差分:是前缀和的逆运算,用于高效地对数组的某个区间进行批量增减操作

下面这个表格整理了最常见的算法思想、核心概念:

|---------------------|-------------------------------------------------|
| 算法分类/思想 | 核心思想/概念 |
| 滑动窗口 | 维护一个可变或固定大小的窗口,在数组/链表/字符串上滑动,高效解决子数组/子串问题。 |
| 双指针 | 使用两个指针协同工作,包括左右指针(用于有序数组的两数之和等)和快慢指针(用于判断链表环等)。 |
| 二分查找 | 在有序搜索空间中,通过比较中间元素快速缩小范围,时间复杂度通常为O(log n)。 |
| 深度/广度优先搜索 (DFS/BFS) | DFS:递归或栈,用于遍历或搜索树/图。 BFS:队列,用于层序遍历或最短路径。 |
| 回溯法 | 一种通过试错寻找所有解的算法,在遇到不可行解时"回溯"至上一步。 |
| 动态规划 (DP) | 将复杂问题分解为重叠子问题,并存储子问题的解以避免重复计算。 |
| 贪心算法 | 每一步都采取当前状态下局部最优的选择,以期望得到全局最优解。 |
| 分治法 | 将问题分解成多个独立的子问题,递归求解后再合并结果。 |

下面以数组 [3,1,4,1,5,9] 为例,展示滑动窗口、双指针、二分查找、DFS/BFS、回溯法、动态规划、贪心算法和分治法的核心思维差异:

各算法详细解析与经典题目

🔍 1. 滑动窗口

  • 核心思想 :维护一个窗口(通常由两个指针leftright界定),在数组或字符串上滑动。通过移动右指针扩大窗口,满足条件后移动左指针收缩窗口,从而在**O(n)**时间内找到满足条件的子区间。

  • 关键点 :用于解决连续子数组/子串问题。窗口内的状态(如字符频率、和、最大值)需要高效维护(常用哈希表或单调队列)。

  • 经典题目

    • 3. 无重复字符的最长子串:用哈希集合记录窗口内字符,确保无重复。

    • 239. 滑动窗口最大值 :使用单调递减队列在O(1)时间内获取窗口最大值。

↔️ 2. 双指针

  • 核心思想:使用两个指针协同遍历,减少时间复杂度。主要有两种形式:

    1. 左右指针 :在有序数组两端向中间移动,用于两数之和、反转数组等。

    2. 快慢指针 :在链表或数组上,以不同速度移动,用于判断循环、找中点、找交点等。

  • 关键点:通常能将O(n²)的暴力解法优化到O(n)。

  • 经典题目

    • 167. 两数之和 II(有序数组):左右指针经典应用。

    • 142. 环形链表 II:快慢指针找到环的入口,是数学和编程的巧妙结合。

🔎 3. 二分查找

  • 核心思想 :在有序的搜索空间中,每次通过比较中间元素,将待搜索区间缩小一半。

  • 关键点 :难点在于边界条件while<还是<=mid加一还是减一)。有寻找精确值、寻找左边界、寻找右边界三种基本变体。

  • 经典题目

    • 34. 在排序数组中查找元素的第一个和最后一个位置:二分查找左右边界的标准模板题。

    • 33. 搜索旋转排序数组:二分查找的进阶,需要在局部有序中判断搜索方向。

🌳 4. 深度/广度优先搜索

  • 核心思想

    • DFS :深度优先,一条路走到黑,用递归 实现。常用于遍历所有路径、排列组合、连通性问题。

    • BFS :广度优先,一层层向外扩展,用队列 实现。常用于最短路径、层序遍历

  • 关键点 :必须注意避免重复访问 (使用visited集合或标记已访问元素)。

  • 经典题目

    • 200. 岛屿数量:网格DFS/BFS的典范,用"淹没"思想标记访问过的陆地。

    • 102. 二叉树的层序遍历:BFS的经典应用。

🧩 5. 回溯法

  • 核心思想 :一种系统性试错 的算法。它沿决策树前进,当探索到某步发现当前选择不满足条件时,就撤销(回溯) 上一步或几步的选择,尝试其他可能性。

  • 关键点 :其核心框架是一个递归函数,包含:选择 -> 递归 -> 撤销选择 。解决全排列、子集、组合、N皇后等需要枚举所有可能解的问题。

  • 经典题目

    • 46. 全排列:回溯法最直观的演示,理解"路径"和"选择列表"。

    • 78. 子集:求所有子集是另一种经典的回溯场景。

🧮 6. 动态规划

  • 核心思想 :将复杂问题分解为重叠的子问题 ,并通过保存子问题的解(通常用数组dp)来避免重复计算,从而高效求解原问题。

  • 关键点 :写出正确的 "状态转移方程" 是核心。思考步骤:1) 定义dp[i]的意义;2) 找出dp[i]如何由dp[0...i-1]推导(状态转移);3) 确定初始值(dp[0]等)。

  • 经典题目(按难度进阶):

    • 70. 爬楼梯 :入门必做,理解dp[i] = dp[i-1] + dp[i-2]

    • 53. 最大子数组和 :理解"dp[i]是以nums[i]结尾的最大和"这一关键定义。

    • 300. 最长递增子序列 :经典的一维DP,dp[i]与之前所有j < i的状态有关。

    • 1143. 最长公共子序列:经典的二维DP,理解文本比较的模型。

🍬 7. 贪心算法

  • 核心思想 :每一步都做出当前看来最优的选择,并希望这样的局部最优能导致全局最优。

  • 关键点:难点在于证明贪心策略的正确性。它不像DP考虑所有子问题,因此效率更高,但适用场景更窄。

  • 经典题目

    • 455. 分发饼干:经典入门题,用小饼干满足小胃口。

    • 122. 买卖股票的最佳时机II:只要今天比昨天贵,就假设昨天买入今天卖出(贪心思想)。

➗ 8. 分治法

  • 核心思想 :将一个大问题分解成若干个独立的、形式相同的子问题 ,递归求解子问题,最后合并子问题的结果得到原问题的解。

  • 关键点 :与DP的关键区别在于,分治法的子问题通常不重叠。归并排序和快速排序是分治法的典型代表。

  • 经典题目

    • 215. 数组中的第K个最大元素:通常使用基于快速排序选择算法的分治思想。

    • 23. 合并K个升序链表:可以两两合并(分治),优于顺序合并。

算法选择指南

  1. 识别问题特征
问题特征 优先考虑算法 原因
看到:连续子数组/子串 滑动窗口 天然适合处理连续区间问题
看到:有序数组查找 二分查找 O(log n) 高效查找
看到:所有可能解/排列/组合 回溯法 系统枚举所有可能性
看到:最优解 + 重叠子问题 动态规划 避免重复计算,得到最优解
局部最优 → 全局最优 贪心算法 高效,但需要证明正确性
可独立分解的子问题 分治法 递归分解,适合并行处理
图/树遍历,最短路径 BFS/DFS 适合层级或深
  1. 混合使用策略

    • DFS + 记忆化 = 记忆化搜索(一种DP实现方式)

    • 二分查找 + 贪心 = 解决"最小化最大值"问题

    • BFS + 优先队列 = Dijkstra算法

相关推荐
listhi5202 小时前
基于蒙特卡洛方法处理电力系统负荷不确定性的解决方案
算法
iAkuya2 小时前
(leetcode)力扣100 29删除链表的倒数第 N 个结点(双指针)
算法·leetcode·链表
@卞2 小时前
01_树的 dfs 序
算法·深度优先
isyoungboy2 小时前
洪水法实现Region RLE的fill_up算法
算法
2401_841495642 小时前
自然语言处理实战——基于BP神经网络的命名实体识别
人工智能·python·神经网络·算法·机器学习·自然语言处理·命名实体识别
wjykp2 小时前
88~93感知机f
人工智能·算法
良木生香2 小时前
【数据结构-初阶】二叉树---链式存储
c语言·数据结构·c++·算法·蓝桥杯·深度优先
Binky6783 小时前
力扣--贪心(2)+动规(1)
算法·leetcode·职场和发展
雾喔3 小时前
1970. 你能穿过矩阵的最后一天 + 今年总结
线性代数·算法·矩阵