算法与数据结构
算法与数据结构需要日常积累
刷题小技巧:
数据结构 + 算法,以类型去leetcode刷题
推荐github算法教程:代码随想录
一、leetcode刷题
2023.12.15
时间复杂度O(n)指的是最坏的情况
算法的logn,忽略底数
2023.12.16
空间复杂度O(n),当消耗空间随着输入参数n随线性增长
计算机一般会有内存对齐的策略,提高效率
2023.12.17
二分查找:左闭右闭 注意边界
移除元素:快慢指针
2023.12.19
有序数组的平方:左右指针
长度最小的子数组:滑动窗口,也是两个指针
2023.12.20
2023.12.21
快速判断一个元素是否出现在集合里,使用哈希法
2023.12.24
两个字符char,ASCII值相加减
链表 统一的逻辑 虚拟头节点
链表最后指向null
2023.12.25
设计链表
2023.12.26
设计链表
类里面有成员变量,构造函数
dummy 虚拟的
pre cur temp 变量取名
链表的最后一个节点指向空节点
2023.12.29
虚拟头节点的使用 ListNode dummy = new ListNode(-1);
链表反转使用双指针法
找环的入口:快慢指针相遇点和head的相遇点,就是环的入口
2023.12.31
数组 length
字符串 length()
for循环内还有for,就要用j,按i、j、k顺序使用
首先是对数组循环,然后是对字符串循环
list set 是contains
map是containsKey
2024.1.2
字符串的方法都是加()的,数组的length没有()
2024.1.3
反转字符串(双指针法)
2024.1.4
KMP算法 字符串匹配
2024.1.6
文本串和模式串
KMP 适用于字符串查找
双指针法的复习
l r fast slow
2024.1.7
2024.1.8
双指针 l r slow fast
2024.1.9
栈与队列
队列 先进先出
栈 后进先出
构造函数:初始化类中的成员变量
栈 push 把值压入栈 pop移除栈顶元素并返回 peek返回栈顶元素
2024.1.10
deque 双向队列 Deque deque = new LinkedList(); push() pop()
2024.1.12
2024.1.13
二叉树的遍历 前序 中序 后序
二叉树的递归遍历(简单一些)
二叉树的迭代遍历 用栈实现
1 | // 前序遍历顺序:中-左-右,入栈顺序:中-右-左 |
层序遍历,也可以使用递归的方式
翻转二叉树
2024.1.14
二叉树的递归和回溯
2024.1.15
相同的树-递归代码:
1 | class Solution { |
二叉树题目大部分使用递归法可以解决
2024.1.16
二叉树 递归
2024.1.17
二叉搜索树 左边节点比根节点小 右边节点比根节点大
2024.1.18
回溯算法
回溯是递归的副产品,只要有递归就会有回溯
如何理解回溯法?
回溯法解决的问题都可以抽象为树形结构,是的,我指的是所有回溯法的问题都可以抽象为树形结构!
因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度就构成了树的深度。
递归就要有终止条件,所以必然是一棵高度有限的树(N叉树)
1 | void backtracking(参数) { |
模板:for循环横向遍历,递归纵向遍历,回溯不断调整结果集
2024.1.19
回溯集合一般用的是LinkedList removeLast()方法移除集合最后的元素
2024.1.20
2024.1.21
void backTracking(){
横向 for
纵向 递归
}
2024.1.22
贪心算法:局部最优推出全局最优 大部分使用for循环比较最优解
2024.1.23
2024.1.24
贪心算法:寻找最优解
2024.1.25
2024.1.26
2024.1.27
动态规划从上一个状态推导而来,贪心局部直接选最优的
2024.1.28
动态规划:
第三层楼梯的状态可以由第二层和第一层楼梯推导出来,可以想到动态规划
动态规划数组为dp
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
2024.1.29
背包问题:01背包和完全背包
2024.1.30
2024.1.31
背包问题:两层for循环
2024.2.1
背包问题:两个for循环
2024.2.3
动态规划:dp数组
当前状态和前面状态会有一种依赖关系,那么这种依赖关系都是动规的递推公式
2024.2.4
股票系列
2024.2.5
股票系列
2024.2.7
子序列系列
2024.2.8
2024.2.9
动规5部曲
2024.2.10
单调栈
2024.2.11
深度优先搜索理论基础 广度优先搜索理论基础
深度优先搜索dfs 广度优先搜索bfs
广搜(bfs)是一圈一圈的搜索过程,和深搜(dfs)是一条路跑到黑然后再回溯
并查集理论基础
并查集常用来解决连通性问题。大白话就是当我们需要判断两个元素是否在同一个集合里的时候,我们就要想到用并查集。
十大排序
快速排序
总结:
数据量规模较小,考虑插入或选择。当元素分布有序时插入将大大减少比较和移动记录的次数,如果不要求稳定性,可以使用选择,效率略高于插入;
数据量规模中等,使用希尔排序;
数据量规模较大,考虑堆排序(元素分布接近正序或逆序)、快速排序(元素分布随机)和归并排序(稳定性);
一般来说不使用冒泡。
二、内功修炼:图解数据结构(小傅哥)
第一章 链表
链表、双向链表、循环链表
prev next
LinkedList 底层是双向链表 查询慢增删快
第二章 数组
内存地址连续
ArrayList 底层是数组 初始值是10,每次1.5倍扩容
扩容完成后,将旧的空间数组迁移到新的空间数组
第三章 队列
单端队列queue 双端队列deque
队列没有特定的容量,deque双端队列可以是LinkedList
PriorityQueue 优先队列
单端队列的实现类:
- PriorityQueue:非阻塞、非线程安全、无边界,支持优先级队列实现类。
- ConcurrentLinkedQueue:非阻塞、线程安全、无边界,基于链接节点的队列实现类。
- ArrayBlockingQueue:阻塞、线程安全、有边界,创建的时候指定大小,一旦创建容量不可改变实现类,默认是不保证线程的公平性,不允许向队列中插入null元素。
- LinkedBlockingQueue:阻塞、线程安全、可选有边界,一个由链表结构组成的可选有界阻塞队列实现类,如果未指定容量,那么容量将等于Integer.MAX_VALUE。
- PriorityBlockingQueue:阻塞、线程安全、无边界,支持优先级排序的无边界阻塞队列实现类。
- DelayQueue:阻塞、线程安全、无边界,使用优先级队列实现的无界阻塞队列实现类,只有在延迟期满时才能从中提取元素。
- SynchronousQueue:阻塞、线程安全、无数据队列,不存储元素、没有内部容量的阻塞队列实现类。
第四章 栈
栈 push添加 pop弹出
后进先出
栈使用 ArrayDeque
第五章 哈希表
哈希散列 即HashMap
第六章 堆
小堆(根节点最小) 大堆(根节点最大)
MaxHeap heap = new MaxHeap() 堆
第七章 字典树
字典树的核心功能:把所有以ba开头的单词全部检索出来了
第八章 二分搜索树
二叉搜索树:右边的值比根节点大,左边的值比根节点小
第九章 平衡二叉树 AVL Tree
左旋、右旋、左旋+右旋、右旋+左旋
第十章 2-3树
2-3树靠旋转调整树高
第十一章 红黑树
红黑树是一种自平衡二叉查找树
红黑树和2-3树的关系:
第十二章 并查集 Disjoint-Set
什么是并查集?