数据结构和算法是计算机发展中纯编程模块重要的总结成果,常见算法和数据结构针对现有的计算机架构、常用业务场景、常见需求进行设计与归纳得出,单纯学习算法的过程比较困难,学习过程也较费劲,需要极大的意志力和兴趣支持。
个人和这块知识的过往
CS专业出身,大概本科三年级学习该内容,虽然也有实践,敲过各类算法,数据结构,却只是停留在大概印象层面。
校招找工作阶段,好好“刷了一波题”,经过自发努力,当时也多少可以AC部分题目。
终于,工作一段时间,不得不反思,总结了,痛定思痛,写吧。
数据结构暂不涉及,多撸题,慢慢就差不多了,本文以算法为主,本文不配图,如有需要自行搜索,有图可以帮助加速理解。
1. 排序算法
以快速排序为例——JDK中的容器在sort时使用该算法,以堆排序为例——曾经面试被问过,没意识到还有这。
1.1快速排序(升序)
a.在区间start,end内,以第一个数为基准值;
b.从末尾往前找小于基准值的数,放置在基准值位置;
c.从第一个数开始找大于于基准值的数,找到则放置在上一个被移动的位置上;
d.循环bc,直到start==end,得到基准值位置pos;
分别对start,pos-1 区间 和 pos+1,end区间递归处理
1.2堆排序:
- 根节点是最值
- R[i].lchild = R[2 * i + 1]
- R[i].rchild = R[2 * i + 2]
- R[i].parent = R[(i - 1) / 2]
- 堆的存储可以使用线性表
- 满二叉树
- 入堆加末尾,出堆将末尾补根
1.2.1构造堆(小顶堆为例):
在线性表上,从第二个节点开始到最后一个节点,各节点和父节点比较,不满足条件则和父节点交换,直到满足堆的条件(到达根节点,或小于父节点,对于新加的节点,只有满足小于父节点,则满足堆的条件)。
public static void heap(int[] data, int n) {
for (int i = 1; i < n; i++) {
int t = i;
while (t != 0 && data[parent(t)] >= data[t]) {
swap(data, t, parent(t));
t = parent(t);
}
}
}
private static int parent(int t) {
return (t - 1) / 2;
}
1.2.1出堆
在堆里面,出堆指的是根节点元素出堆,元素出堆,不满足堆条件,将最后一个元素补至根节点,调整堆:即将根元素下沉至合适位置,使得二叉树满足堆条件。
下沉过程:和子节点比较,同较小的节点交互位置,直到小于所有节点。
public static int pollMin(int[] data) {
int ret = data[0];
data[0] = data[data.length - 1];
siftDown(data, data.length - 1);
return ret;
}
private static void siftDown(int[] data, int n) {
int i = 0;
while (true) {
if (i >= n - 1) break;
// find max in i, i.lchild, rchild
int l = 2 * i + 1;
int r = 2 * i + 2;
int min = i;
if (l <= n - 1 && data[l] < data[i]) min = l;
if (r <= n - 1 && data[r] < data[min]) min = r;
// 当前节点已经最小则调整结束
if (min == i) break;
swap(data, i, min);
i = min;
}
}
1.2.3入堆
加在末尾,并上浮,直到根或满足堆条件。
public static void addMin(int[] data, int x) {
data[data.length - 1] = x;
int i = data.length - 1;
while (parent(i) >= 0 && data[i] < data[parent(i)]) {
swap(data, i, parent(i));
i = parent(i);
}
}
1.2.4堆排序
根节点出堆后,将当前末尾元素补至根,下沉根节点,调整堆。
public static void addMin(int[] data, int x) {
data[data.length - 1] = x;
int i = data.length - 1;
while (parent(i) >= 0 && data[i] < data[parent(i)]) {
swap(data, i, parent(i));
i = parent(i);
}
}
1.3二叉查找树
递归判断是否满足条件,左边严格小于根,右边严格大于根。
对于根节点,如果为空,则满足条件,否则需要满足左右子树为二叉排序树,同时值的大小满足排序条件。
boolean isBinarySortedTree(Node root, long min, long max){
if (root == null) return true;
return isBinarySortedTree(root.left, Long.MIN_VALUE, root.val) &&
isBinarySortedTree(root.right, root.val, Long.MAX_VALUE) &&
root.val > min &&
root.val < max;
}
————————分割线,未来继续————————
2.图
图使用二维矩阵、或者邻接表表示,行标代表节点,存储各节点的出度。
3.回溯法
n皇后
子集
去重子集
4.动态规划
最长回文子序列
最大正方形