相对位置更适合移植到不同设备
为链表的头结点,利于删除操作的统一化
对cur.next赋值才是连接
链表插入操作中先连接后面线,利用完cur.next 再给他赋值
递归:例如全排列:选好第一个,剩下的全排列,别忘了回溯
用二叉树表示多叉树或森林:对于某个结点有firstchild和nextsibling两种不互斥的选择
博弈问题中两个人都很聪明,当你把局面递归的交给对手,对手返回必输时你必赢
每一个变量都对应一个数据域空间,而赋值的根本是变量的数据域的改变(传参也是一种赋值,如list.add (a))
对象的实例:数据域是地址(引用)类型的变量
一个对象没有构造方法,系统默认提供无参构造器可用;子类未显示调用父类构造器,会自动调用父类无参的,父若无报错
霍夫曼编码:对某一文件,出现频率低的词在二叉树偏下层,路径长些,编码位数多一点,然后由下往上构造树
c与c++的acm大神多,让他们转java一定不会很多,这是你的优势
二叉查找树:平时不忙的时候排好序,应对关键时刻的查找,将关键时刻的时间压力平均到平时
—————– 4/27 ——————————-
Node[]数组可以表示树,完全二叉树连Node中的lchild,rchild都不需要就可以找到孩子(leftNo = parentNo*2+1……)
看到右边字体一列有很多的选项,我们只需要修改basic里面的,点击展开Basic,最下面有 Text Font 这个选项,点击,然后右边的Edit被激活了
霍夫曼编码中每次都取出现次数(频率)最小的两个(贪心):一种思路是压入优先级队列,相比于遍历求最小两值;当两者都进行一次时,绝对后者快(前者还要排序),但是当他们进行好多次时,前者优势就显示出来了
多类型数据运算全都转换成位数多的;向位数少的类型强制转换会被截断
关于Java的继承问题:父类的静态部分is linked to子类,而非静态部分is copied to(隐式); Father a = new Son()中Father是范围限定,其中的函数可被子类重写,这也是实现多态的基础
实现接口的类必须重写接口里的方法(而其他地方此类的对象会调用此方法),比abstract更抽象,而抽象的意味着不可变,多变的东西尽量把他们放到子类中
子类继承的implement是父类的
5种主动引用(比如:用new实例化一个类时、读取或者设置类的静态字段时(不包括被final修饰的静态字段,因为他们此前已经被塞进常量池并可见了)、以及执行静态方法,反射,Class.forName)
会触发类的初始化(将使静态变量可见(此前类加载的时候已经分配内存),并调用静态块———只执行一次),而其他普通变量将在new实例的时候分配内存可见
静态部分从属于类;
非静态内部类是附属在外部类对象上的,需要先实例化一个外部类的对象,通过外部类对象才能实例化非静态内部类;而静态内部类可以看做是直接附属在外部类上的,这个静态代表附属体是外部类,而不是外部类实例;
两个线程针对同一个变量,thread1还没有store,thread2就load。解决方法:用volatile取消线程私有内存,每个线程里对内存的改变都会立刻执行
———————– 5/1 ——————————————–
尾递归优化解决的是内存溢出的问题,而垃圾回收解决的是内存泄露的问题 。递归是我们用来理解算法的一个方法,当用代码来实现的时候基本都可以转换成非递归的代码实现
递归转非递归 对于一次循环 :此时无用但以后还有用的就循环入栈,以后没用了就出栈一个看看看
———————– 5/3 ———————————————
不仅要赢得今天的战争,还要赢得未来的每一场
Kruaskal算法:对于一条待选集合中当前最小的一个边,如果其两端点的根节点不一样(说明两点不连通),就将当前边加入到选定集合
prime算法:数组closedge[待定集合中的顶点]中包含着 到选定集合的参数(权值和对应的连接到选定集合中的点),更新时选择一个(非0,0代表已经并入)最小的权值的点并入选定集合,并同时更新其他待选集合中的点
两个栈实现一个队列中:如果b栈空了,就再把a栈中的数据入到b栈,如果b没空,b中本来先出的栈顶元素就被后来的a栈元素顶替了,不符合队里的顺序
———————– 5/6 ———————————————
红黑树的建立:用递归(自上而下的找到要插入的位置, 然后自下而上的根据原则更新当前节点相关链接)
对于LSD: 每个字符出现的次数(频率)就是相对位置,前几项相加就可以得出绝对位置来(这是按字符串某一位置分类)。 从数字低位越往前,重排数组的能力越大(权值越大,对位置的决定能力越大)
count[r+1] = …. ; count[r]代表的是r前面的数《 对应 》的值 ;还要注意的是当要取r时的值的时候,也用count[r+1],对应的
对于MSD: 从左边的第一个字符开始,(hi-lo)小于阈值就字符串排列就可以了,否则数据分类,针对每一段数据递归进入下一个字符
这里涉及到一个阈值的最优选择问题
———————- 5/8 ———————————————-
对于Quick3string:对于sort方法,根据首字母将数据分为 小于 等于 大于三个子数组,
三个子数组分别相应的 针对本位置字符递归调用sort(因为本位置并不有序),针对下一位置字符递归调用sort,针对本位置字符递归调用sort
dijkstra算法:从一个固定出发点点求出到各点的最短路径 (贪心) → 维护一个数组 Distance[待定集合中的顶点] 表示 出发点 经过 选定点 到 当前[待定集合中的顶点] 的最短路
循环n-1次,每次:找最短点并入选定集合;选定集合变了,也就要更新Distance[]数组
Floyd算法: 任意两点之间的最短路径 (动态规划) → 维护一个邻接矩阵,初始化表示的两点之间的直达;然后不断的加入可选跳点(直到全部加入),
看一下 加入跳点相比原先直达路径(三段线的最短路径以前已经求出来了) 变长还是变短来更新邻接矩阵
//对于算法描述,先 说维护怎样的数据结构,再 说算法的核心东西
——————— 5/13 ———————————————-
c语言中链表的结构体变量必须malloc,因为在此结构体变量中 必须 有进入下一个结构体的地址(而只有malloc才会返回地址类型的变量)
哦,有一种可能,就是你忘了初始化什么变量,导致一会儿碰到那块空间是干净的就蒙对了,下次碰到那块空间有数据就崩溃了……
拓扑排序:当某一顶点的入度为0时,此顶点就可以执行,同时使得邻接结点的入度–;(只要保证弧两边的顶点的相对顺序)
关键路径:(顶点是状态,弧是任务)针对每个顶点按照拓扑排序从左往右取最大作为最早开始时间,从右往左取最小作为最晚完成时间(最晚开始时间=最晚完成时间-此任务所需时间)
——————– 5/16 ———————————————–
单词查找树:每一个结点有一个value 和 一个256大小的next[下标是key字符串中第d个单词对应的ACSII值]数组,其值指向下一个结点
List[] l = new ArrayList[10];
运行时编译器只能看到ArrayList,而看不到泛型的String类型参数。数组由于无法确定所持有元素的类型,所以不允许初始化;(Java Language Specification明确规定:数组内的元素必须是“物化”的)
插入排序:将后面的一个数(可以保存到哨所)插入到前面有序的序列中(包括找到插入位置 和 交换)
对插入排序的改进 1.二分查找插入的地方:最后形成low == mid == high,如果要插到mid后面,让low加一个,反之让high减一个,最后low和high错位时跳出,将哨兵插入high+1
2.希尔排序:先将序列分成几部分(分法是1,6,11,16…为一组,2,7,12,17…为一组)分别排序,直到增量为1时的排序,体会这个思路
三向单词查找树:某结点的 leftNode 和 rightNode与此节点是一个d上的,只有midNode才会进行到d+1(d是key字符串的第几个字符)
——————– 5/17 ———————————————–
语言是层出不穷的(kotlin),技术层出不穷(AI),抓住一个原则:使他商业化的转换成为有用的东西(学以致用,我一直惊叹于人类的认知在现实中又一次被验证)
冒泡:交换相邻两个元素(在n趟排序中,每趟要解决的是将一个元素沉到底,找到家)
快排:交换远距离的两个(改进冒泡,在n趟排序中,每趟要解决的也是将一个基准元素找到家,但位置不确定,同时实现左边的都小于基准,右边大于基准)
基本思路概括为:(从小到大排序)要想填左边的坑,从右边倒着找小于基准元素挖出填上,再填新坑
堆排:(大顶堆:父比子大,所以堆顶一定是最大的元素;是一个完全二叉树,如果在一个数组中子与父之间的位置有公式)
(从大到小排序)倒着建立一个大顶堆,将堆顶输出,将最后一个挪到堆顶,然后调整大顶堆,然后循环
归并:将数组分为多部分 分别排序,再将有序的数组段归并成较大的有序数组段,直至整个数组有序
递归:大问题不断分解; 动态规划:小问题不断的合成
——————– 5/21 ———————————————–
KMP:一个退化的有限状态自动机
dfa数组的值为回退或者前进的下一个状态
0 A 1 B 2 A 3-C 是pat,其他分支是txt可能出现的其他字符串情况
针对当前的状态j,要匹配字符C(正好是pat中的)的dfa数组值为j+1(代表匹配成功);字符B的dfa数组值 为X状态下的要匹配字符B的值(即2);
对于X的理解,从X的更新来看只和pat有关,如果j状态要正好要匹配一个pat.charAt(j),重启状态X也正好要匹配这个字符,重启状态 就j+1;如果不是,重启状态X就回退 ;(用一句话X = dfa[X][pat.charAt(j)];解决)
所以X代表着j状态时的pat中 能够重复前、后缀中 前者的末位置(也是KMP能够在pat与dfa匹配时剪枝的的核心)
Boyer-Moore 字符串匹配算法:pat整体向右匹配txt,pat局部的每个字符倒着匹配txt,遇到不匹配的字符,pat就整体向右移动到 最近一个至少匹配txt中此字符 的位置(启发式)
——————- 5/24 ————————————————