Skip to content

Latest commit

 

History

History
 
 

data-structure-algorithms

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

title 数据结构与算法:Java开发者的必备修炼
date 2025-05-09
categories Algorithm

🚀 数据结构与算法开篇

数据结构与算法

💡 关于怎么刷题的帖子:


🎯 专栏介绍

本专栏致力于为Java开发者提供全面的数据结构与算法学习资源,涵盖从基础概念到高级应用的完整知识体系。通过系统性的学习和实践,帮助开发者提升编程能力,掌握解决复杂问题的核心技能。

📚 专栏特色

  • 🎯 系统性学习:从基础到进阶,循序渐进
  • 💻 Java实现:所有代码示例均使用Java语言
  • 🔥 实战导向:结合LeetCode经典题目
  • 📊 可视化理解:丰富的图表和动画演示
  • 🎨 美观排版:精心设计的文档格式

📊 第一部分:数据结构分类

数据结构是计算机存储、组织数据的方式,是算法的基础。掌握各种数据结构的特点和应用场景,是成为优秀程序员的必经之路。

📏 线性数据结构

线性数据结构是指数据元素之间存在一对一关系的数据结构,元素按线性顺序排列。

📋 1. 数组 (Array)

数组结构示意图:
Index: [0] [1] [2] [3] [4]
Value: [12][45][78][23][56]
       ↑   ↑   ↑   ↑   ↑
      连续的内存地址空间
  • 特点:连续存储,支持随机访问
  • 时间复杂度:访问O(1),插入/删除O(n)
  • Java实现:int[]、ArrayList

🔗 2. 链表 (Linked List)

单链表结构示意图:
[Data|Next] -> [Data|Next] -> [Data|Next] -> null
     |              |              |
    节点1           节点2           节点3

双链表结构示意图:
null <- [Prev|Data|Next] <-> [Prev|Data|Next] <-> [Prev|Data|Next] -> null
  • 特点:动态存储,插入删除高效
  • 时间复杂度:访问O(n),插入/删除O(1)
  • Java实现:LinkedList

📚 3. 栈 (Stack)

栈结构示意图:
    |     |  <- top (栈顶)
    |  C  |
    |  B  |
    |  A  |
    |_____|  <- bottom (栈底)
    
操作:LIFO (后进先出)
  • 特点:后进先出(LIFO)
  • 时间复杂度:push/pop/peek都是O(1)
  • Java实现:Stack、Deque

🚶 4. 队列 (Queue)

队列结构示意图:
出队 <- [A][B][C][D] <- 入队
      front        rear
      
操作:FIFO (先进先出)
  • 特点:先进先出(FIFO)
  • 时间复杂度:enqueue/dequeue都是O(1)
  • Java实现:Queue、LinkedList

🌳 非线性数据结构

非线性数据结构是指数据元素之间存在一对多或多对多关系的数据结构,形成复杂的层次或网状结构。

🌲 5. 二叉树 (Binary Tree)

二叉树结构示意图:
        A (根节点)
       / \
      B   C
     / \ / \
    D  E F  G (叶子节点)
    
层次:
第0层:    A
第1层:   B C
第2层: D E F G
  • 特点:每个节点最多有两个子节点
  • 时间复杂度:搜索/插入/删除O(logn)~O(n)
  • Java实现:TreeMap、TreeSet

🏔️ 6. 堆 (Heap)

最大堆示意图:
        90
       /  \
     80    70
    / \   / \
  60  50 40  30
  
特点:父节点 >= 子节点 (最大堆)
数组表示:[90,80,70,60,50,40,30]
  • 特点:完全二叉树,堆序性质
  • 时间复杂度:插入/删除O(logn),查找最值O(1)
  • Java实现:PriorityQueue

🕸️ 7. 图 (Graph)

无向图示意图:
    A --- B
   /|     |\
  / |     | \
 D  |     |  C
    |     | /
    E --- F

邻接矩阵表示:
    A B C D E F
A [ 0 1 0 1 1 0 ]
B [ 1 0 1 0 0 1 ]
C [ 0 1 0 0 0 1 ]
D [ 1 0 0 0 1 0 ]
E [ 1 0 0 1 0 1 ]
F [ 0 1 1 0 1 0 ]
  • 特点:顶点和边的集合,表示复杂关系
  • 时间复杂度:遍历O(V+E),最短路径O(V²)
  • Java实现:Map<Node, List<Node>>

🗂️ 8. 哈希表 (Hash Table)

哈希表结构示意图:
Hash函数:key → hash(key) % size → index

Key: "apple"  → hash("apple") = 5 → index: 5 % 8 = 5
Key: "banana" → hash("banana")= 3 → index: 3 % 8 = 3

Table:
[0] → null
[1] → null  
[2] → null
[3] → "banana" → value
[4] → null
[5] → "apple" → value  
[6] → null
[7] → null

冲突处理(链地址法):
[3] → ["banana",value1] → ["grape",value2] → null
  • 特点:基于键值对,快速查找
  • 时间复杂度:平均O(1),最坏O(n)
  • Java实现:HashMap、HashSet

⚡ 第二部分:常见算法

算法是解决问题的步骤和方法,是程序设计的核心。掌握各种算法的思想和实现,能够帮助我们高效地解决各种复杂问题。

🔢 1. 排序算法

排序算法是计算机科学中最基础也是最重要的算法之一,掌握各种排序算法的特点和应用场景至关重要。

算法 时间复杂度(平均) 时间复杂度(最坏) 空间复杂度 稳定性
冒泡排序 O(n²) O(n²) O(1) 稳定
选择排序 O(n²) O(n²) O(1) 不稳定
插入排序 O(n²) O(n²) O(1) 稳定
快速排序 O(nlogn) O(n²) O(logn) 不稳定
归并排序 O(nlogn) O(nlogn) O(n) 稳定
堆排序 O(nlogn) O(nlogn) O(1) 不稳定
计数排序 O(n+k) O(n+k) O(k) 稳定
基数排序 O(nk) O(nk) O(n+k) 稳定

🔍 2. 搜索算法

搜索算法用于在数据集合中查找特定元素,不同的搜索算法适用于不同的场景。

  • 线性搜索:O(n) - 适用于无序数组
  • 二分搜索:O(logn) - 适用于有序数组
  • 哈希查找:O(1) - 适用于HashMap/HashSet
  • 树搜索:O(logn) - 适用于二叉搜索树
  • 图搜索:DFS/BFS - O(V+E)

🕸️ 3. 图算法

图算法是处理图结构数据的重要工具,广泛应用于网络分析、路径规划等领域。

🔍 3.1 图遍历

  • 深度优先搜索(DFS):O(V+E)
  • 广度优先搜索(BFS):O(V+E)

🛣️ 3.2 最短路径

  • Dijkstra算法:O((V+E)logV) - 单源最短路径
  • Floyd-Warshall算法:O(V³) - 全源最短路径
  • Bellman-Ford算法:O(VE) - 含负权边

🌲 3.3 最小生成树

  • Prim算法:O(ElogV)
  • Kruskal算法:O(ElogE)

📋 3.4 拓扑排序

  • Kahn算法:O(V+E)
  • DFS算法:O(V+E)

🎯 4. 动态规划

动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。

🏗️ 4.1 基础DP

  • 斐波那契数列:O(n)
  • 爬楼梯:O(n)
  • 最大子序和:O(n)

📝 4.2 序列DP

  • 最长递增子序列(LIS):O(nlogn)
  • 最长公共子序列(LCS):O(mn)
  • 编辑距离:O(mn)

🎒 4.3 背包问题

  • 0-1背包:O(nW)
  • 完全背包:O(nW)
  • 多重背包:O(nWlogM)

📏 4.4 区间DP

  • 最长回文子串:O(n²)
  • 矩阵链乘法:O(n³)

🎯 5. 贪心算法

贪心算法是一种在每一步选择中都采取在当前状态下最好或最优的选择,从而希望导致结果是最好或最优的算法。

  • 活动选择问题:O(nlogn)
  • 分数背包:O(nlogn)
  • 最小生成树(Prim/Kruskal):O(ElogV)
  • 霍夫曼编码:O(nlogn)
  • 区间调度:O(nlogn)

🔄 6. 分治算法

分治算法是一种很重要的算法,字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题。

  • 归并排序:O(nlogn)
  • 快速排序:O(nlogn)
  • 二分搜索:O(logn)
  • 最大子数组和:O(nlogn)
  • 最近点对:O(nlogn)

🔙 7. 回溯算法

回溯算法是一种通过穷举所有可能情况来找到所有解的算法。当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择。

  • N皇后问题:O(N!)
  • 数独求解:O(9^(n*n))
  • 全排列:O(n!)
  • 子集生成:O(2^n)
  • 组合问题:O(C(n,k))

📝 8. 字符串算法

字符串算法是处理文本数据的重要工具,广泛应用于文本搜索、模式匹配等领域。

  • KMP算法:O(n+m) - 字符串匹配
  • Rabin-Karp算法:O(n+m) - 字符串匹配
  • 最长公共前缀:O(S) - S为所有字符串长度和
  • 字典树(Trie):插入/查找 O(m)
  • 后缀数组:O(nlogn)

🧮 9. 数学算法

数学算法是解决数学问题的计算方法,在编程中经常需要用到各种数学算法。

  • 最大公约数(GCD):O(logn)
  • 快速幂:O(logn)
  • 素数筛选:O(nloglogn)
  • 模运算:O(1)
  • 组合数学:O(nlogn)

🔢 10. 位运算算法

位运算是计算机中最底层的运算,掌握位运算技巧可以写出更高效的代码。

  • 位运算基础:O(1)
  • 状态压缩DP:O(n*2^m)
  • 子集枚举:O(2^n)
  • 位操作技巧:O(1)

🏗️ 11. 高级数据结构算法

高级数据结构算法是建立在基础数据结构之上的复杂算法,能够解决更复杂的问题。

  • 并查集:O(α(n)) - 接近常数时间
  • 线段树:O(logn) - 区间查询/更新
  • 树状数组:O(logn) - 前缀和查询
  • 平衡树(AVL/红黑树):O(logn)
  • 跳表:O(logn)

🎯 第三部分:LeetCode经典题目

LeetCode是程序员刷题的重要平台,通过系统性的刷题练习,可以快速提升算法能力。以下是按类型分类的经典题目。

📋 1. 数组类题目

数组是最基础的数据结构,掌握数组的各种操作技巧是算法学习的基础。

🔧 基础操作

  • 1. 两数之和 - 哈希表优化
  • 26. 删除排序数组中的重复项 - 双指针
  • 27. 移除元素 - 双指针
  • 88. 合并两个有序数组 - 双指针

🔍 搜索与查找

  • 33. 搜索旋转排序数组 - 二分搜索
  • 34. 在排序数组中查找元素的第一个和最后一个位置 - 二分搜索
  • 35. 搜索插入位置 - 二分搜索
  • 153. 寻找旋转排序数组中的最小值 - 二分搜索

👆 双指针技巧

  • 15. 三数之和 - 排序+双指针
  • 16. 最接近的三数之和 - 排序+双指针
  • 18. 四数之和 - 排序+双指针
  • 42. 接雨水 - 双指针
  • 11. 盛最多水的容器 - 双指针

🪟 滑动窗口

  • 3. 无重复字符的最长子串 - 滑动窗口
  • 76. 最小覆盖子串 - 滑动窗口
  • 209. 长度最小的子数组 - 滑动窗口
  • 438. 找到字符串中所有字母异位词 - 滑动窗口

🔗 2. 链表类题目

链表是动态数据结构,掌握链表的操作技巧对于理解指针和递归非常重要。

🔧 基础操作

  • 206. 反转链表 - 迭代/递归
  • 21. 合并两个有序链表 - 双指针
  • 83. 删除排序链表中的重复元素 - 单指针
  • 82. 删除排序链表中的重复元素 II - 双指针

👆 双指针技巧

  • 141. 环形链表 - 快慢指针
  • 142. 环形链表 II - 快慢指针
  • 160. 相交链表 - 双指针
  • 19. 删除链表的倒数第 N 个结点 - 快慢指针

🔄 复杂操作

  • 234. 回文链表 - 快慢指针+反转
  • 143. 重排链表 - 找中点+反转+合并
  • 148. 排序链表 - 归并排序
  • 23. 合并K个排序链表 - 分治/优先队列

📚 3. 栈与队列类题目

栈和队列是重要的线性数据结构,在算法中有着广泛的应用。

📚 栈的应用

  • 20. 有效的括号 - 栈匹配
  • 155. 最小栈 - 辅助栈
  • 225. 用队列实现栈 - 设计问题
  • 232. 用栈实现队列 - 设计问题

📈 单调栈

  • 496. 下一个更大元素 I - 单调栈
  • 503. 下一个更大元素 II - 单调栈
  • 739. 每日温度 - 单调栈
  • 84. 柱状图中最大的矩形 - 单调栈

4. 树类题目

二叉树遍历

  • 94. 二叉树的中序遍历 - 递归/迭代
  • 144. 二叉树的前序遍历 - 递归/迭代
  • 145. 二叉树的后序遍历 - 递归/迭代
  • 102. 二叉树的层序遍历 - BFS

二叉树性质

  • 104. 二叉树的最大深度 - DFS
  • 111. 二叉树的最小深度 - BFS/DFS
  • 226. 翻转二叉树 - DFS
  • 101. 对称二叉树 - DFS

二叉搜索树

  • 98. 验证二叉搜索树 - 中序遍历
  • 700. 二叉搜索树中的搜索 - 二分搜索
  • 701. 二叉搜索树中的插入操作 - 递归
  • 450. 删除二叉搜索树中的节点 - 递归

树的路径问题

  • 112. 路径总和 - DFS
  • 113. 路径总和 II - DFS+回溯
  • 124. 二叉树中的最大路径和 - DFS
  • 257. 二叉树的所有路径 - DFS+回溯

5. 图类题目

图的遍历

  • 200. 岛屿数量 - DFS/BFS
  • 695. 岛屿的最大面积 - DFS/BFS
  • 994. 腐烂的橘子 - BFS
  • 130. 被围绕的区域 - DFS/BFS

拓扑排序

  • 207. 课程表 - 拓扑排序
  • 210. 课程表 II - 拓扑排序

联通分量

  • 547. 省份数量 - 并查集/DFS
  • 684. 冗余连接 - 并查集
  • 721. 账户合并 - 并查集

6. 动态规划类题目

基础DP

  • 70. 爬楼梯 - 基础DP
  • 198. 打家劫舍 - 线性DP
  • 213. 打家劫舍 II - 环形DP
  • 53. 最大子序和 - Kadane算法

序列DP

  • 300. 最长递增子序列 - LIS
  • 1143. 最长公共子序列 - LCS
  • 72. 编辑距离 - 字符串DP
  • 5. 最长回文子串 - 区间DP

背包问题

  • 416. 分割等和子集 - 0-1背包
  • 494. 目标和 - 0-1背包
  • 322. 零钱兑换 - 完全背包
  • 518. 零钱兑换 II - 完全背包

状态机型DP

  • 121. 买卖股票的最佳时机 - 状态机DP
  • 122. 买卖股票的最佳时机 II - 状态机DP
  • 123. 买卖股票的最佳时机 III - 状态机DP
  • 188. 买卖股票的最佳时机 IV - 状态机DP

7. 回溯算法类题目

排列组合

  • 46. 全排列 - 回溯
  • 47. 全排列 II - 回溯+去重
  • 77. 组合 - 回溯
  • 78. 子集 - 回溯

分割问题

  • 131. 分割回文串 - 回溯+动态规划
  • 93. 复原IP地址 - 回溯

棋盘问题

  • 51. N 皇后 - 回溯
  • 37. 解数独 - 回溯

8. 贪心算法类题目

区间问题

  • 435. 无重叠区间 - 贪心
  • 452. 用最少数量的箭引爆气球 - 贪心
  • 55. 跳跃游戏 - 贪心
  • 45. 跳跃游戏 II - 贪心

9. 字符串类题目

字符串匹配

  • 28. 实现 strStr() - KMP算法
  • 459. 重复的子字符串 - KMP算法

回文串

  • 125. 验证回文串 - 双指针
  • 5. 最长回文子串 - 中心扩展
  • 647. 回文子串 - 中心扩展

10. 位运算类题目

  • 136. 只出现一次的数字 - 异或运算
  • 191. 位1的个数 - 位运算
  • 338. 比特位计数 - 位运算+DP
  • 461. 汉明距离 - 位运算

🎯 刷题建议

  1. 由易到难:从Easy开始,逐步提升到Hard
  2. 分类练习:按数据结构和算法类型分类刷题
  3. 反复练习:重要题目要反复练习,形成肌肉记忆
  4. 总结模板:每种题型都要总结解题模板
  5. 时间管理:每天固定时间刷题,保持连续性
  6. 记录总结:建立错题本,定期回顾总结

🛠️ 学习工具推荐

📚 在线平台

🎥 学习资源

💻 开发工具

  • IDE:IntelliJ IDEA、Eclipse
  • 调试:LeetCode插件、本地调试
  • 版本控制:Git管理代码
  • 笔记:Markdown记录学习心得

💡 记住:数据结构和算法是程序员的内功,需要持续练习和积累

🚀 建议:每天至少刷一道LeetCode,坚持100天必有收获

📚 资源:LeetCode中国 | 算法可视化

🎉 加油:相信通过系统性的学习,你一定能够掌握数据结构和算法的精髓!