算法
我想有个夏天
希望生活简单点
展开
-
斐波那契数(动态规划)
斐波那契数:当前的数等于前两个数的和,0,1,1,2,3,5.。。。。递归写法我想大家肯定都不陌生了public int get(int n) { if(n < 2) { return n; } return get(n - 1) + get(n - 2);}这个是我刷剑指offer看到的,看到瞬间哇,竟然可以这么写public int get(int n) { int i = 0; int j = 1; while(n-- > 0) { j += i;原创 2020-12-09 20:58:02 · 182 阅读 · 0 评论 -
堆排序递归和非递归
在了解堆排序之前,基本的二叉树的概念是需要知道的完全二叉树:叶子节点在最后一层或者次一层,且节点从左往右连续大根堆:任何根节点都比他的左右子节点都要大i为节点在数组中的索引,求节点的父节点:(i - 1) / 2, 求节点的左节点 i * 2 + 1,求节点的右节点 i * 2 + 2在构建一个堆之前,我们需要先把他们的左右节点构建成堆,所以我们从下往上依次构建堆,由于叶子节点是没有子节点的,所以从最后一个节点的父节点开始构建,想画个个图,可是实力实在不允许那就都放在代码中吧,老铁干了这段代码,先写原创 2020-12-09 20:41:39 · 249 阅读 · 0 评论 -
KMP算法(思想真的不复杂)
在了解KMP之前,我们需要了解两个概念,字符串的前缀,和字符串的后缀字符串的前缀,我举个例子你们就懂了,一个字符串abcde,它包含的前缀有,{a, ab, abc, abcd}字符串的后缀,{bcde, cde, de, e}知道这两个概念后,我们就可以来聊kmp的思想了,现在假如我们需要知道一个字符串(这个字符串我们称为被匹配字符串)中是否包含另一个字符串(这个字符串我们称为被目标字符串),我们最容易想到的自然就是遍历匹配字符串中每一个字符为开头,然后逐一向下匹配。这样自然是可以也很容易想到,但是原创 2020-11-11 16:05:14 · 130 阅读 · 0 评论 -
骑士周游算法(跳马)
骑士周游算法:主要就是两个思想深度遍历和回溯,以当前点为目标,算出下一个能走的点的集合,然后以下一个能走的目标,然后算出下下个能走的目标,最后不能走时,看有没有完成,没有完成就回退,这里需要一个辅助数组来进行判断点是否有没有走。接下来就是算法了//标记点位是否走过private boolean[] flag;//多少行,这里设置成8行8列private int Y = 8;private int X = 8;//标记算法是否完成private boolean isComplete = fal原创 2020-11-06 22:16:53 · 912 阅读 · 0 评论 -
迪杰斯特拉算法(Dijkstra)-Java实现
迪杰斯特拉算法也是求两点之间最短路径的算法,它的思想和普利姆算法有点相似,不断通过已找到点集合和未找到点之间的集合之间的最短路径。这个算法需要用到三个数组,一个是存储结点是否已经访问,一个是结点到起始点的最短距离,还有一个是结点到起始点第一个需要经过的点。我们不断通过迭代更新这三个数组,最终就可以得到每个点到起始点的最短距离数组了。接下来可以结合代码理解,我也把代码注释写的尽量详细。//是否已经访问过private boolean[] isVisited;//第一个经过的结点private in原创 2020-11-06 21:50:42 · 279 阅读 · 0 评论 -
弗洛伊德算法(floyd)
弗洛伊德算法和迪杰斯特拉算法都是求两点之间最短路径的问题,弗洛伊德算法使用了动态规划的思想,用二维矩阵记录了所有点之间最短的距离,虽然代码只有几行,但是思想还很值得回味的。其主要的思想就是两个点之间的直接距离能否使用第三个点来缩短。公式:vj > vk + kj,这个公式讲的就是,三个点v,j,k。v点如果需要到j点,v直接到j的距离,是否要大于v到某个中间点k的距离加上k到点的距离,然后依次遍历所以点为中间点,就可以得出所有点之间的最短距离,这样讲可能有点很难理解。下面我举个例子吧。比如现在有5原创 2020-11-06 20:50:05 · 1025 阅读 · 0 评论 -
克鲁斯卡尔算法(kruskal)
我自己感觉,克鲁斯卡尔算法比普利姆算法更好理解,它就两个要点,排序和判断是否成环。排序:我们把两两相邻的边根据边的权值,从小到大依次排序,这个十大排序算法可以自己选一个去实现下,刚好还可以回忆下以前的算法,下面我们使用冒泡来实现边的排序。是否成环:这个也是这个算法里比较难的一个点了,这里使用了并查集,每次添加一条边时候,我们需要去寻找这两个点是否有相同的父节点,如果有说明成环了,我们就可以选择下一条边了,直到有n-1条边。如果不了解并查集的,可以看看下面这一篇文章,讲的很通俗易懂。(https://原创 2020-11-05 22:52:35 · 618 阅读 · 0 评论 -
普利姆算法(Prim)
普利姆算法和克鲁斯卡尔算法都是求连接图中所有结点的最短路径,也就是最小生成树。普利姆算法其实就是不断获取已经访问结点和未访问结点之间的最短边来获取所有结点间的最短路径,也可以认为是广度+贪婪。接下来看算法的实现,这里只给出关键代码,基本的图数据结构可以自己实现。//结点数量private int[] vertexs;//矩阵实现图private int[][] edges;//n:为指定开始的结点public void prim(Graph graph , int n) { //这里我们需要原创 2020-11-05 22:07:58 · 796 阅读 · 0 评论 -
图的深度遍历和广度遍历(java实现)
在说图的广度遍历和深度遍历之前,我们可以回想下,树的先序遍历和层次遍历,先序遍历我们是不是从根节点一直递归到叶子节点,然后再慢慢回退,图的深度遍历也是类似的。图的深度遍历,只需要额外一个数组记录顶点是否有访问过,下面就使用矩阵来实现图,和图的深度遍历。//这里n为顶点的数量private boolean[] isVisited = new boolean[n];//这里为矩阵构建的图1为边private int[][] edges;public void dfs(int n){ //这里打印对原创 2020-11-04 23:10:21 · 304 阅读 · 0 评论 -
树的后序遍历(递归和非递归)
树的后序遍历:左右根,代码写起来还是很简单的,就几行代码。public void postOrder(Node node) { if(node.getLeft() != null){ postOrder(node.getLeft()); } if(node.getRight != null){ postOrder(node.getRight()); } System.out.print(node.getValue());}这里如果不是很熟悉,可以自己debug下,在纸上自己画画过程原创 2020-11-03 23:35:18 · 622 阅读 · 0 评论 -
树的层次遍历和确定层次问题
树的层次遍历其实就是使用了队列的特性,从跟节点开始,把左右节点分别加入队列,出来时候,自然就是一层一层的打印出来的。代码还是很简单的public void levelOrder(Node root) { LinkedList<Node> queue = new LinkedList(); queue.add(root); while(queue.size() > 0){ Node node = queue.removeFirst(); System.out.print(n原创 2020-11-03 22:07:58 · 708 阅读 · 0 评论 -
递归实现钢条切割问题(Java版)
钢条切割问题递归有两种思想: 1.切割一刀分别获取两两边的最优解相加,获取两两相加的最优解和不切割的比较这样就可以得出可以分割的最大价值。 公式:r(n)=max(p[n] , r(1)+r(n-1) , r(2)+r(n-2) ,……,r(n-1)+r1)public static int cut(int[] p, int value) { if (value == 0) { return 0; } else { i原创 2020-10-23 22:46:41 · 482 阅读 · 1 评论 -
冒泡排序及优化(JAVA实现)
冒泡排序的的思想还是很简单的,通过相邻的两个数比较,直到比较完无序区的数,无序区最大的数就到了末尾。接下来看一段冒泡排序的动图,可以更好的理解。图片中把比较完无序区,我们称为一趟,我们每一趟都可以得出一个最大值,n-1次我们就可以得到一个有序的数组了,无序区我们用当前值和它后面一个值比较,如果当前值大于后一个值,那么我们就交换他们,这样每次大的都在后面,当比较完整个无序区,我们就得到无序区最大的值了。接下来就是代码了:public static void bubblingSort(int[] ar原创 2020-10-14 23:12:35 · 179 阅读 · 0 评论