算法知识
文章平均质量分 60
徐乙
这个作者很懒,什么都没留下…
展开
-
约瑟夫环
仅做个人记录题就不说了在看网上的参考答案前,我先自己瞎分析了几波,下面是我的思路分析0.链表,时间复杂度太高了1.有没有既能维护链表特性,又能维护数组特性的东西?看来是没有,要不然也不会有这么多平衡查找树了2.平衡查找树,对于这一题肯定是一点都不适合的啊,因为我的每个节点并不需要存储元素啥的3.采用数组,记录每一位之前的所有已占用的节点。白痴思路,复杂度依然高,而且实现难度也变高了4.找数学规律5...原创 2018-06-06 22:20:01 · 195 阅读 · 0 评论 -
归并排序
typedef struct Node { int val; struct *Node;}Node, LinkedList;int main() {}void cal(Node *L, int left, int right) { if(left int j = (int) sqrt(right - left原创 2018-01-18 17:24:02 · 176 阅读 · 0 评论 -
Bellman-Ford和松弛技术
适用条件 有向图 但是没有负环比之迪杰斯特拉 在于他可以计算负的权值边负环是什么环负环就是至少有一条边是负数松弛技术这里是发现了2+2=4所以不能是负环,因为这样下去,会一直更新,越来越小,可以自行体会所以Bellman-Ford就是遍历所有的边,这个遍历需要进行点的个数的次数。原创 2018-01-18 17:22:35 · 766 阅读 · 0 评论 -
正确理解Dijkstra(迪杰斯特拉)算法
下面给出一张在各大计算机网络教材中使用的经典例图。我们的目的是求出A到各点的最短路径,初始集合U={A,B,C,D,E,F}。取元素的规则是取当前A到各点最短且没被取过的点(即在U中的点)。我们一开始从U中取出A,并更新各点距离。当前A到D=1,A到B=2,A到另外的点的距离是无穷大,所以我们取出D。取出D后A到各点的距离。当A打算A->D->B作为A到原创 2018-01-04 23:16:05 · 6557 阅读 · 0 评论 -
字符串A和B的扩展距离,简单dp(动态规划)
字符串比较问题(动态规划算法) 对于长度相同的2个字符串A和B,其距离定义为相应位置字符距离之和。2个非空格字符的距离是它们的ASCII码之差的绝对值。空格与空格的距离为0,空格与其他字符的距离为一定值k。 在一般情况下,字符串A和B的长度不一定相同。字符串A的扩展是在A中插入若干空格字符所产生的字符串。在字符串A和B的所有长度相同的扩展中,有一对距离最小的扩展,该距离称为字符串A原创 2017-12-27 20:04:28 · 4082 阅读 · 0 评论 -
杭电ACM OJ 1043 Eight 八数码 8种方法 花式解决
EightTime Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 27216 Accepted Submission(s): 7257Special JudgeProblem DescriptionThe 1原创 2017-12-14 21:44:53 · 1691 阅读 · 1 评论 -
八数码第八境界——IDA*+逆序数判无解
(请先看前面7大境界)IDA*是什么?它已经不再像A*一样通过bfs+优先队列+曼哈顿距离3者结合来做。它是通过曼哈顿距离,求出最大搜索深度,还是和上篇文章的例子一样来说。我们这里使用的是曼哈顿距离。我们希望的路径假设是4 8 71 2 x5 6 3我们的结束路径是1 2 34 5 67 8 x原创 2017-12-14 19:58:12 · 777 阅读 · 0 评论 -
八数码第七境界——A*之曼哈顿+康托展开判重+回溯记录路径+逆序数判无解
(请先看前面6大境界)A*其实就是以bfs为基础的,就是给了bfs一些条件,让它以优先队列的形式进行。想快速掌握A*可以看http://blog.csdn.net/qq_36523667/article/details/78786160A*有两种距离计算公式:一种是曼哈顿距离:横向距离+纵向距离一种是欧氏距离:两点间的直线距离我们这里使用的是曼哈顿距原创 2017-12-14 18:56:48 · 780 阅读 · 0 评论 -
八数码第六境界——双向BFS+康托展开判重+回溯记录路径+逆序数判无解
(建议先看前5大境界)这里相比于上一境界,又增加了一个逆序数判无解的操作,因为第5个境界,双向bfs在无解的时候,显现出了比单向bfs更低的效率(因为他出了更多次的队列,相比于单向 bfs)。什么是逆序数?比如2 4 3 1。依次看下去,2比1大,4比3大,4比1大,3比1大。所以逆序数就是4。所以我们得知了逆序数就是体现在一个逆字上。相比于在正常序列下1234。有多少原创 2017-12-13 23:54:51 · 445 阅读 · 0 评论 -
深入理解逆序数+八数码原理
什么是逆序数?比如2 4 3 1。依次看下去,2比1大,4比3大,4比1大,3比1大。所以逆序数就是4。所以我们得知了逆序数就是体现在一个逆字上。相比于在正常序列下1234。有多少前面的数比后面的数大的这种情况,就是逆序数了。逆序数为什么可以判八数码的无解?(八数码: 1 2 3 4 5 6 7 8 x) 因为如果起始状态和目标状态,如果把目原创 2017-12-14 01:24:15 · 6521 阅读 · 2 评论 -
八数码第五境界——双向BFS+康托展开判重+回溯记录路径
(请先看前4大境界)这里较上一境界,就是把反向的BFS,弄成了双向的BFS。先不说算法的优劣,就光这个双向的BFS,就是指的记录和学习的。很简单,在结合之前所学的基础上,把单向扩展成双向即可。结构体struct node { char str[10]; int mark,num; int index,has原创 2017-12-13 23:06:26 · 448 阅读 · 0 评论 -
堆排序
有两种形式1.大的数在堆的顶部2.小的数在堆的顶部就是从树的底层出发,汇集到顶部,使得最大的数到达了父节点。这个时候就得到了初始堆。然后把这个数放到最后一行的最后一个。但是这个时候初始堆的性质又不满足了,所以这个时候又从底层出发,使得大的数到达顶部(忽略那个放在最后的一个的最大的数)、这个时候再把最大的数放在刚刚最大的树的相近的位原创 2018-01-18 17:28:03 · 152 阅读 · 0 评论 -
最近点对分治
先要排除一种思维 最短不一定是横坐标相近的两个点最短可能有这种情况. . .所以就复杂了分成3份考虑左边右边中间先求出左边和右边的,左边和右边的最小值进行比较会得到一个最小值d(左边和右边通过递归的形式得到)用这个d去给中间的进行剪枝 如果是中间线正负d距离以外的,都剪枝,因为它不可能比d短。把中原创 2018-01-18 17:32:11 · 335 阅读 · 0 评论 -
快排及时间复杂度简单证明
快排这里不再赘述 主要是时间复杂度 先写一下快排代码void quick_sort(int a[], int start, int end) { int val = a[start]; int s = start; int e = end; while(s < e) { while(s < e && a[e] > val) e...原创 2018-03-29 09:44:49 · 14347 阅读 · 3 评论 -
二分法的一个变形
仅做个人记录原始二分法返回的是indexpublic int halfSearch(int a[], int s, int e, int key) {while(s <= e) {int mid = (s + e)/2;int m = mid/2;if(m==key) return mid;else if(m < key) e = mid-1;else if(m > key) ...原创 2018-04-08 23:28:30 · 237 阅读 · 0 评论 -
排序算法:二分排序(插入排序+二分查找)
插入排序就是一直向后读,第一个数,加入前面已经有序的一串数里。而插入排序是笨笨的一个个向前找的,可以优化一下,用二分查找找到合适的位置。插入排序代码void Insertsort2(int a[], int n) { int i, j; for (i = 1; i < n; i++) if (a[i] < a[i - 1]) {...原创 2018-03-03 22:43:35 · 3024 阅读 · 0 评论 -
排序算法:插入排序(代码优化)
必须得看看http://blog.csdn.net/morewindows/article/details/6665714一开始第一个数,后来读到第二个数,加进去,强行排序一波,再往后读一个,强行排序一波。代码1:void Insertsort2(int a[], int n) { int i, j; for (i = 1; i < n; i++) i...原创 2018-03-03 22:22:02 · 193 阅读 · 0 评论 -
排序算法:冒泡排序(代码优化)
http://blog.csdn.net/morewindows/article/details/6657829是必看的例:长度为N的数组从0开始进行两两左右交换,那么必然可以把最大数放到最右端。第二次只需要从第1个到N-1个进行同样的操作就可以了。所以你只需要开两层循环:外层:仅仅记录下这是第几次操作,每进行一次操作,我们需要遍历的长度都要减1内层:进行一个遍历,遍历到N-i即可代码1://冒泡...原创 2018-03-03 21:53:10 · 238 阅读 · 0 评论 -
排序算法:快速排序(挖坑填数+分治)
复习一下 浓缩一下http://blog.csdn.net/morewindows/article/details/6684558这篇文章是必看的例:72 6 57 88 60 42 83 73 48 85只需要挖72,然后从85开始向前找一个比72小的,放到72,挖出新坑,从6开始找比大的,找到再挖出新坑,循环即可,直到左右标记位相遇。这样就是完成一次。然后再对72左边和右边的区间递归,递归终止...原创 2018-03-03 21:34:18 · 352 阅读 · 0 评论 -
二叉搜索树
借鉴自http://blog.csdn.net/eson_15/article/details/51138663数组 查找方便 增删不便链表 查找不便 增删方便所以用二叉搜索树会比较好ps:为什么数组查找方便,链表查找不便,如果数组是乱序的,岂不是仍然要遍历一遍?实际上,全部遍历一遍,时间复杂度都是O(n),但是数组的内存地址是连续的,链表的内存地址是不连续的,所以对于数组,CPU的地址寄存器就不...原创 2018-02-12 21:57:36 · 162 阅读 · 0 评论 -
有向无回路图的最短路径和拓扑排序
先要了解无回路就是这种形式的所以如果没有这种形式的东西 就可以得出一个线性的图这就是拓扑排序做的事了得到这样一个图以后,就可以利用松弛技术了,只需要遍历每个点,再松弛每个点所指向的点的那条边即可。时间复杂度奇低原创 2018-01-18 17:46:20 · 757 阅读 · 0 评论 -
算递归式的时间复杂度
第一种 代换法 给他假设一个时间复杂度 然后去验证比如T(n)=2T(n/2)+O(n)我们就可以假设时间复杂度是nlgnT(n)=2T(n/2)+O(n)当c>=1的时候成立第二种 递归树法求出每一层的代价 根据总和 得出渐进复杂度上界 比上面的方法更加容易得出猜测第三种 主方法对T(n) = aT(n/b) + f(n)的形式有奇效分别对应了原创 2018-01-18 17:41:30 · 666 阅读 · 0 评论 -
分治法求得树的最大深度
先提供一种不是特别符合分治思想的思路 也很好int max = 0;void cal(Node *n, int depth) { if(depth > max) max = depth; if(n -> leftChild != NULL) cal(n -> leftChild, depth + 1); if(n -> rightChild != NULL)原创 2018-01-18 17:34:56 · 324 阅读 · 0 评论 -
八数码第四境界——暴力反向BFS+康托展开判重+打表+回溯记录路径
(请先看前面3重境界)由于第三重境界要开一个vector来嵌套许多vector来记录路径,那绝对是开销很大。所以我们采用回溯记录路径。思路:原来我们是采用康托展开,比如求出12345678x在全排列的第几个(这里无疑是第一个),用来判断这种状态是否已经到达过了,这里就是vis[1]=1代表已经访问过,vis[1]=0代表未访问过。在每次访问以后都置为1。而现在我们这里不一样了。原创 2017-12-13 22:34:10 · 527 阅读 · 0 评论 -
最长上升子序列——O (nlogn)算法原因解析!为什么这样可以求出来!(附带动态规划dp + 二分查找讲解)
什么是最长上升子序列网上流传着一个O (nlogn)算法,大体是这样的。模拟一个栈,如果当前的数比栈顶元素大,就要入栈,如果比栈顶元素小,就二分查找到刚好比当前数大的数,然后进行替换。本例的流程是这样的。2 入栈 当前栈:25 比2大 入栈 当前栈:2 53 比5小 替换5 当前栈:2 34 比3大 入栈 当前栈: 2 3 41比2小 替换2 当原创 2017-11-25 16:33:38 · 1065 阅读 · 2 评论 -
八数码第三境界——暴力反向BFS+康托展开判重+打表
(在看了第1、2境界后,再看本文)这里唯一新增的操作就是打表,所以需要理解打表这个概念。这里就是bfs找出所有的可能,并且都记录下来。记录的方式。vectorint>res[N]; while(!q.empty()) { g=q.front();q.pop(); int t =原创 2017-12-13 16:49:12 · 456 阅读 · 0 评论 -
大数问题:大数加法 与 大数乘法 最简单大数乘法
大数加法很简单,大叔乘法只是以大数加法为基础的,光从难度来说,两者差不多。思路:这里没有借鉴别人牛逼的算法,现在也没有这个需求,就用最通俗的思路自己想了一个。先举一个简单的例子所以乘法就是每一位个位数相乘再乘以多少次方就可以了,这个多少次就是两者的数组位置的索引相加。看看关键代码for (int i = 0; i ; i ++) { for原创 2017-11-20 23:27:59 · 1112 阅读 · 0 评论 -
BFS+优先队列——迷宫最短路径——两种最优方法比较及详细图解
http://blog.csdn.net/qq_36523667/article/details/78638354这个链接里是一道迷宫题。用到了BFS+优先队列。我一直百思不得其解优先队列到底优先在哪了?我感觉和直接bfs没啥区别?后来证明做法不一样,思路也不一样。所以这里引出另一种最优的做法。正常的bfs黑色是当前的点,黄色是即将探索的点,把黄色的依次原创 2017-11-30 00:25:26 · 7831 阅读 · 2 评论 -
回溯法大成!以回溯法实现栈的出栈情况的遍历为例子,轻松帮你深刻领悟回溯法
这里用回溯法实现了 栈的出栈情况的遍历 。虽然这个题有更好的做法,但是你如果用回溯法做这道题,做完后一定会对回溯法有这更高境界的领悟,而且在整个设计算法,debug算法的过程中会感受到一种酣畅淋漓的快感。因为这个题看似很小,其实规模很大,要考虑方方面面的问题,很多很多。上题。输入一个序列 比如 123。你进栈的顺序必须是按照这个序列来,但是你可以这样,进1,然后在2进入前,把1出栈原创 2017-11-19 23:06:41 · 1930 阅读 · 0 评论 -
全排列的本质——康托展开以及本质原理分析——选取第N个——由序列推知第几个
先用一个例子简单介绍一下这个原理12345找出这个序列全排列的第16个原创 2017-11-29 00:16:49 · 1025 阅读 · 0 评论 -
算法-把n个数的每一种排列情况都列出来(排列组合)-全排列-字典序算法(一看就懂)
首先需要介绍字典序算法原创 2017-11-14 18:01:15 · 3818 阅读 · 0 评论 -
算法 分治 平面最近点对
问题平面最近点对问题是指:在给出的同一个平面内的所有点的坐标,然后找出这些点中最近的两个点的距离.暴力法//1.暴力法private static double force(List list) { int size = list.size(); double distance; double min = Double.MAX_VALUE;原创 2017-11-04 15:59:06 · 1043 阅读 · 0 评论 -
辗转相除法最简单最通俗证明
先上辗转相除的代码while (true) { int t = a % b; if (t == 0) break; else { a = b; b = t; }}为什么要这么做?我们来证明余数也是公因数的倍数a,b两个数,(a>b),肯定是有一个公因数1的,或者也可能有一个更大的公因数z。不管是1还是更大的,原创 2017-11-13 22:39:29 · 3859 阅读 · 1 评论 -
快速求质因子(一定程度上,比辗转相除好得多)
借鉴自我的朋友,http://my.csdn.net/raalghul。而他的qq也是需要输入他qq号的质因子才能加他的,所以很有趣,我想他讨教了求质因子的方法,然后加了他,哈哈。方法:按正常方法找一个数的因子,用一个for循环,遍历到sqrt(num)前,一个个看能否除的通。这里有点不一样,找到一个质因子后,num = num/i,减小了num的长度,直接加快了效率。为什么可原创 2017-11-15 23:58:44 · 5025 阅读 · 1 评论 -
回溯法求全排列-非递归形式-代码还没优化过
回溯法递归的很好写,非递归的难写很多很多!(看之前必须得理解递归形式的回溯法)难写在哪?因为回溯法递归,每次递归都有一个for循环,可以完美避开重复的路径。然而非递归的避免重复路径还要另花心思,这就是他的难点。如何规避重复路径?我们通过查找的时候,添加一个条件,就是回溯回来的时候,这个数不光要取没被使用的数,还要取一个比之前这个位置上的数更大的数,因为我原创 2017-11-17 19:40:09 · 748 阅读 · 0 评论 -
最简回溯法求全排列-递归形式 快速领悟回溯法窍门
思路:比如123,在第一个位置摆放的时候,有3种情况,用一个for循环,第一次找的是1,1就被标记了,在找第二位第三位的时候,1就不可以用了。再找第二位,剩下2和3,由于1被标记了,只可以找2或者3,先取的是2,取后标记2。再找第三位,剩下了3,由于12都被标记了,只可以找3,所以直接就是3。第一个序列123就出来了。由于3只有一种情况,他一次就执行完了。看到第二位,剩下2和3,2原创 2017-11-15 20:39:11 · 1025 阅读 · 0 评论 -
(最高性能)高效求一个数是否为素数,6倍原理
6倍原理就是,素数只可能出现在6的倍数附近。原因:6的倍数以外的数是什么?拿12为例子。9 10 11 12 13 14原创 2017-11-15 22:09:28 · 3897 阅读 · 3 评论 -
八数码第二境界——暴力反向BFS+康托展开判重
(八数码的第一境界必须看了再看本文)与上文有所区别,上文采用的是string存储状态,这里采用的是char[],可以增加性能。上文采用的是map判重,这里采用的是康托展开看看是全排列的第几个来判重。所以本文最大的问题是领悟康托展开。因为这里是1到x占据9个位置,所以就等于是求这9个位置的全排列了,而了解全排列的人会知道,康托展开是做全排列最好的方式。如果不太清楚用康托展开求全排原创 2017-12-13 15:04:51 · 713 阅读 · 0 评论 -
最长上升子序列——回溯法
回溯法其实算是一种暴力法,但是我们必须先学会暴力法再去考虑更优化的算法,不然真的会。。。boom不能交叉,所以你从一边开始遍历的时候,另一边被匹配的点只会一次比一次高。所以只需要记录下被匹配那一边的index就好了。回溯法思路如果这个位置接下去搜索不到弃掉如果这个位置接下去搜索得到可以选择匹配也可以不匹配先判断回溯条件if原创 2017-11-25 00:45:58 · 923 阅读 · 0 评论 -
八数码第一境界——暴力反向BFS+存状态
这题首先会遇到一个问题:BFS无法实施为什么会无法实施?正常情况,x从队列中取出,8、6入队8从队列中取出,x和8交换,7、5入队这个时候下一个要出队列的是6,但是你x在8原来的位置,怎么实施交换?所以队列中应该入的是状态,可能很抽象,但是下面的图不抽象。我们还是看6要出队列的时候的情况,就是第三行第一个。我们发现他可以出队列了。出队列,向左原创 2017-12-13 01:42:08 · 1066 阅读 · 0 评论