已经是9.30日,感觉互联网公司校招都快差不多了,自己刷的题也差不多了,之后还得做实验室的差事和专心做毕设,所以想要停止刷题好好总结了。
本帖记录:
1)数据结构总结
2)算法总结
1.数据结构总结
主要以思维导图的方式进行总结,总结每一种
数据结构的关联的常用技巧
,以及一些对应的典型例题。
笔者认为,根据思维导图,按图索骥,温故而知新,能够对数据结构有个大致的掌握,再具体了解一些技巧与特定问题。
数据结构类型
可分为
线性
和非线性
:
线性如数组、链表,其中队列和栈为操作首先的线性表
非线性如树和图。
其中:链表、树和图往往涉及到递归
。
1. 数组、字符串(字符数组)
vector
和string
常用技巧:
- 排序:
快排
、归并
和堆排序
必会- 双指针
典型例题
- 旋转矩阵
- 螺旋矩阵
2. 队列
先进先出,
queue
;还包含双端队列deque
和优先队列priority_queue
常用技巧:bfs
典型例题
- 设计循环队列
- 用两个队列实现一个栈
- 双端队列用于滑动窗口
- 优先队列用于寻求TOP-K
3. 栈
后进先出,
stack
典型例题
- 字符串解码
- 逆波兰表达式
- 用两个栈实现一个队列
- 最小栈
单调栈
4. 哈希表
unordered_map
和map
,低层分别为双向链表和红黑树;前者无序,后者有序。
可以用迭代器构造vector数组。
lambda正则表达式用于排序。
典型例题
- 两数之和
5. 链表
单向链表ListNode*
和双向链表list
struct ListNode{
int val;
ListNode* next;
ListNode(int _val):val(_val){
this->next = NULL;
};
};
常用技巧:
- 合并链表
- 局部反转链表
- 快慢指针
- 指针先行K步
- 哑巴节点+双指针
典型例题
- 合并有序链表
- 反转链表
- 链表排序
- 回文链表
- 删除链表中的重复节点
- 相交链表
- 判断链表是否有环
6. 树:TreeNode*
struct TreeNode
{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
三种遍历+层序遍历
递归
+分治
6.1 二叉树
分为完全二叉树、完美二叉树;平衡二叉树AVL树
,二叉搜索树BST
。
完全二叉树中特殊的又包含堆heap
,大顶堆和小顶堆。
平衡二叉树AVL树
:任何节点的左右子树的深度之差都不超过1.
二叉搜索树BST
:左子树上的所有节点的值均比根节点小,右子树上的所有节点的值均比根节点大;中序遍历为单调序列。
6.2 n叉树
前缀树Trie
和SLAM中的八叉树octotree
。重点了解前缀树,也称为字典树(类中包含子节点数组和isEnd标识位)。
class Trie {
private:
bool isEnd;
Trie* next[26];
public:
Trie() {
isEnd = false;
memset(next, 0, sizeof(next));
}
// ... 略
}
7. 图 graph
通常可使用邻接矩阵(二维数组)来表示。
涉及到:
1)最短路径
:迪杰斯特拉算
2)最小生成树
:Prim算法、Kruskal算法、Boruvka算法
3)并查集UnionFind
:用于划分集合,数据之间的关联。包括:初始化unionCreate
、路径压缩find
、合并两个集合unionTwo
和判断两个数据是否属于同一个集合isConnected
。
class UnionFind {
private:
vector<int> size;
vector<int> parent;
int count;
public:
// 并查集合,初始化大小
void unionCreate(int n)
{
this->count = n;
parent.assign(n,0);
size.assign(n,0);
for(int i=0;i<n;i++){
parent[i] = i;
size[i] = 1;
}
}
// ...略
}
2.算法总结
2.1 排序
重点掌握3种,
快速排序
、归并排序
和堆排序
一定要能够手撕以上三种排序算法!
此外,冒泡、插入排序、选择排序、计数排序也要熟练于心。
对排序算法
总结的博客:排序算法
2.2 查找
有序数组:
- 二分查找
- 双指针
2.3 搜索
广度优先搜索BFS
深度优先搜索DFS
回溯backTrack:注意考虑如何剪枝!
2.4 动态规划
- 背包问题
- 最长公共子序列
- 最长回文子串
- 爬楼梯
- 编辑距离