算法导论
文章平均质量分 92
SpringRolls
我是一只小拉吉
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
DP 斐波那契数列js NC68
斐波那契数指的是这样一个数列:0、1、1、2、3、5、8、13、21、…… 用数学公式表示为:简单的来说就是 后一项是前两项之和。方法一:递归时间复杂度:O(n^2),空间复杂度:O(n)// 递归法function Fibonacci(n) { if (n < 2) { return n; } else { return Fibonacci(n - 1) + Fibonacci(n - 2); }}由.原创 2020-11-20 09:54:37 · 317 阅读 · 0 评论 -
二叉树中是否存在节点和为指定值的路径 NC9
给定一个二叉树和一个值\ sumsum,判断是否有从根节点到叶子节点的节点值之和等于\ sumsum的路径,例如:给出如下的二叉树,sum=22返回true,因为存在一条路径5→4→11→2 的节点值之和为 22。思路分成三种情况,(1)节点不存在,返回false(2)节点只有一个的时候,判定是否左子和右子均为空,且sum值等于该节点值(3)递归的具体操作,递归左子和右子,同时更新sum的值,且结果为或的关系var hasPathSum = function (root, s...原创 2020-11-18 16:07:59 · 485 阅读 · 0 评论 -
二叉树(最大)深度js NC13
最大深度是指树的根结点到最远叶子结点的最长路径上结点的数量。树的深度 = 左子树的深度和右子树深度中最大者 + 1function TreeDepth(pRoot) { //树的深度=左子树的深度和右子树深度中最大者+1 if (pRoot === null) return 0; var leftDep = TreeDepth(pRoot.left); var rightDep = TreeDepth(pRoot.right); return原创 2020-11-18 14:58:42 · 596 阅读 · 0 评论 -
二叉树各种遍历(前中后序遍历,递归非递归,DFS,BFS)js
树的中序遍历(非递归)思路:先将p入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为p,出栈,访问p.val,再中序遍历p的右子树。原创 2020-11-18 14:26:14 · 644 阅读 · 0 评论 -
两个链表的第一个公共节点 NC66
方法一:双指针假设两个链表公共长度为C,不公共的长度分别为A、B。则两个链表长度分别为A+C,B+C。设两个指针,让第一个链表走完之后,跳到第二个链表开始走,共A+C+X1距离;同理第二个链表走完后调到第一个链表开始走,走B+C+X2距离。那么两个指针相遇时,由 A+C+X1 = B+C+X2,距离不为负,得X1=B,X2=A,所以最后两个指针走的距离都是A+B+C,刚好在第一个公共点相遇。复杂度分析时间复杂度 : O(m+n)空间复杂度 : O(1)//双指针var ge..原创 2020-11-11 17:02:29 · 345 阅读 · 0 评论 -
环形链表第一个入环节点 NC3
思路:1)首先判断是否有环,有环时,返回相遇的节点,无环,返回null2)有环的情况下, 求链表的入环节点 fast再次从头出发,每次走一步, slow从相遇点出发,每次走一步, 再次相遇即为环入口点。证明:快指针与慢指针均从X出发,在Z相遇。此时,慢指针行使距离为a+b,快指针为a+b+n(b+c)。所以2*(a+b)=a+b+n*(b+c),推出a=(n-1)*b+n*c=(n-1)(b+c)+c;得到,将此时两指针分别放在起始位置和相遇位置,...原创 2020-11-10 20:06:09 · 552 阅读 · 0 评论 -
判断链表是否有环 NC4
思路:快慢指针用一快一慢指针,开始两个指针都指向链表头部。慢指针每次向前走一步,快指针每次向前走两步。如果有环,则两个指针最终一定会相遇。这种方法无须额外的空间。//给定一个链表,判断链表中是否有环。var hasCycle = function(head) { if(!head || !head.next) return false let slow = head let fast = head.next while(slow != fas原创 2020-11-10 10:44:25 · 174 阅读 · 0 评论 -
判断链表是否为回文链表 NC96
方法一:利用数组(栈)遍历链表,用数组把数据存下来,然后再进行一次遍历,同时用数组反向地与之比较,这样就可以判断是否回文。这个方法时间复杂度是O(n)pop() 移除数组的最后一项,返回移除的项 shift() 移除数组的第一项,返回移除项var isPalindrome = function (head) { let nums = []; while (head) { nums.push(head.val); head = head.ne...原创 2020-11-09 13:56:38 · 400 阅读 · 0 评论 -
寻找链表倒数第K个节点 (NC69)/ 删除链表倒数第N个节点(NC53)
第一种方法是先循环一遍链表确定结点个数n,则倒数第k个结点就是就是正数的第n+1-k个,然后在遍历一次链表就可以找到指定结点了,但显然需要遍历两遍链表。第二种方法可以使用两个指针,第一个指针先走k-1步,然后第二个指针开始走。当第一个指针移动到最后时,第二个指针正好指向倒数第k个结点,只需要遍历一遍链表,显然更高效。...原创 2020-11-08 14:25:14 · 380 阅读 · 0 评论 -
划分链表(Partition List)
对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于等于这个值的结点移到前面,大于该值的结点在后面,同时保证两类结点内部的位置关系不变。思路:采用双指针思想,维护node1指针作为前面的插入指针,node2作为后面的删除指针。此时分为两种情况:若链表首节点值大于或等于给定值,首先找到其后第一个小于给定值的节点删除并插入到 node2 之前作为头节点,并令 node1 指向它,然后将 node2 指向原删除节点的下一个节点 若链表首节点值小于给定值,那么首先找到从左往右第一个大于或等于给原创 2020-11-07 16:10:04 · 613 阅读 · 0 评论 -
单链表删除节点
//给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。//返回删除后的链表的头节点。原创 2020-11-07 11:09:50 · 5046 阅读 · 0 评论 -
链表去重(删除重复元素)
未排序链表去重 O(n^2)思路:第一重循环从链表的头节点开始,枚举一个保留的节点,这是因为我们保留的是「最开始出现的节点」。第二重循环是枚举「最开始出现的节点」的下一个结点,到链表的末尾结束,将所有与保留节点相同的节点全部移除。//移除未排序链表中的重复节点。保留最开始出现的节点。(两层循环)//输入:[1, 2, 3, 3, 2, 1]//输出:[1, 2, 3]var removeDuplicateNodes = function (head) { var slow =原创 2020-11-03 18:26:23 · 3926 阅读 · 0 评论 -
反转单链表
现在有一个单向链表如下图所示:反转后如下所示:/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } *//** * @param {ListNode} head * @return {ListNode} */var reverseList = function(head) { //le转载 2020-11-03 13:48:16 · 301 阅读 · 0 评论 -
数组去重(至少两种方法)js
方法1:普通版,利用indexOf去重新建一个数组,遍历去要重的数组,当值不在新数组的时候(indexOf为-1)就加入该新数组中。indexOf() 方法:返回某个指定的字符串值在字符串中首次出现的位置。如果要检索的字符串值没有出现,则该方法返回 -1。//方法1:普通版,利用indexOf去重function arrayUnique(arr){ var len = arr.length; var res = []; for(var i = 0; i < len原创 2020-11-02 22:37:11 · 1617 阅读 · 0 评论 -
数组乱序(打乱数组,至少两种方法)js
数组随机排序(shuffle)方法1:时间复杂度 O(n^2)// 方法2:随机抽取法, 时间复杂度 O(n^2)function randomSortArray(arr) { let backArr = []; while (arr.length) { //Math.random():返回 [0,1) 之间的一个随机数 let index = parseInt(Math.random() * arr.length); // 利用数组长度生成随机原创 2020-11-02 13:47:27 · 18151 阅读 · 1 评论 -
字符串逆序(翻转整数字符串)js
11原创 2020-11-02 10:09:56 · 461 阅读 · 0 评论 -
二分查找(非递归/递归)js
二分查找(折半查找),是一种在有序数组中查找特定元素的搜索算法。查找过程可以分为以下步骤:(1)首先,从有序数组的中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。(2)如果目标元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。(3)如果某一步数组为空,则表示找不到目标元素。非递归算法:// 非递归算法function binary_search1(nums, target) { var原创 2020-11-01 22:03:28 · 389 阅读 · 0 评论 -
js排序算法:冒泡、选择、插入、快排★★★ 归并★
一、冒泡排序算法描述如下: 1.比较相邻的两个元素,如果前一个比后一个大,则交换位置。2.第一轮的时候最后一个元素应该是最大的一个。3.按照步骤一的方法进行相邻两个元素的比较,这个时候由于最后一个元素已经是最大的了,所以最后一个元素不用比较。算法实现:/*** @Author spring* @DateTime 2020-10-29* @param {arr} 待数组* @return {arr} 排好序的数组* @description 这是一个冒泡排序算..原创 2020-11-01 12:15:51 · 486 阅读 · 0 评论 -
单源最短路径SSSP之松弛操作
单源最短路径SSSP算法中使用了 松弛(relaxation)操作,即更新两点的最短路径形象的理解:原来用一根橡皮筋连接a、b两点,现在有一点v到b的距离更短,则用v点替换橡皮筋的a点,使得v、b连接在一起。这样缓解橡皮筋紧绷的压力,使其变得松弛,即松弛操作。我们规定每个节点都有一个 dist 值,dist[v] 值记录的是从源点可达的顶点v的最短距离,每个节点也都有一个p指针指向...原创 2019-10-21 13:19:22 · 1297 阅读 · 0 评论 -
单源最短路径SSSP之Bellman-Ford算法
Bellman-Ford算法和Dijkstra算法都是求解图的最短路径的算法。Bellman是求单源点到各个顶点的最短路径,适用条件为有向或无向图,权重可为负值。当存在负权环路时,算法返回一个false值。该算法效率比较低,需要对边进行 |V|- 1 次松弛操作Bellman-Ford算法寻找单源最短路径的时间复杂度为O(V*E)。(V为给定图的顶点集合,E为给定图的边集合)两者区别在于:...原创 2019-10-13 20:53:38 · 1561 阅读 · 0 评论 -
Dijkstra算法解析及Java代码实现(附图)
所谓单源,即求从一个点出发,到其他各点的最短路径,也就是说 :如果这个图有n个点,我们要求n-1个路径。算法概述Dijkstra算法使用了广度优先搜索(BFS)解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树。该算法常用于路由算法或者作为其他图算法的一个子模块。该算法的时间复杂度是n的平方,可以使用堆优化。但是,要注意一点,Dijkstra算法只能适...转载 2019-10-13 19:02:23 · 731 阅读 · 0 评论 -
并查集解析及Java代码实现(附图)
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。它的功能主要有:1、找到某个节点的头节点2、查询两个节点是否在同一个集合里3、合并两个集合具体算法为:在给定的一个集合中,所有的节点都指向第一个节点,而第一个节点指向自身,查询是否位于同一集合,我们直接查询节点的父节点是否为同一个节点(该节点指向自身),合并两个集合时,我们将集合的父节...原创 2019-10-12 14:06:07 · 323 阅读 · 0 评论 -
Prim算法解析及Java代码实现(附图)
Prim算法普里姆(Prim)算法,是用来求加权连通图的最小生成树的算法。基本思想 : 对于图G而言,V是所有顶点的集合;现在,设置两个新的集合U和T,其中U用于存放G的最小生成树中的顶点,T存放G的最小生成树中的边。 从所有uЄU,vЄ(V-U) (V-U表示出去U的所有顶点)的边中选取权值最小的边(u, v),将顶点v加入集合U中,将边(u, v)加入集合T中,如此不...转载 2019-10-05 23:16:54 · 1207 阅读 · 0 评论 -
Kruskal算法解析及Java代码实现(附图)
最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树。example:例如,对于如上图G4所示的连通网可以有多棵权值总和不相同的生成树。克鲁斯卡尔(Kruskal)算法克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法,基于连续的按照最小边...转载 2019-10-05 22:09:11 · 985 阅读 · 0 评论 -
Kosaraju算法解析及Java代码实现(附图)
强连通分量强连通分量只可能存在于有向图中,无向图中是不存在强连通分量的。下图很形象地指出了图中所包含的强连通分量。上图中存在5个强连通分量(阴影部分)。拓扑排序定义:给定一副有向图,将所有的顶点排序,使得所有的有向边均从排在前面的元素指向排在后面的元素。如下图所示,左边是一个有向无环图,箭头方向代表了其执行方向,也就是边的方向。右边是通过计算得到的拓扑排序,其实从图中...原创 2019-10-01 00:06:30 · 957 阅读 · 0 评论 -
Tarjan算法解析及Java代码实现(附图)
以下概念为有向图中的定义:强连通: 在一个有向图G里,如果有两个点(a、b)可以相互到达,我们就叫这两个顶点(a,b)为强连通。强连通图: 如果在一个有向图G中,每两个点都强连通(可以相互到达),我们就叫这个图为强连通图。强连通分量(SCC):在一个有向图G中,有一个子图,这个子图每2个点都满足强连通,我们就叫这个子图叫做 强连通分量,孤立的点也是一个强连通分量。例:下图中,子...原创 2019-09-25 22:47:40 · 1679 阅读 · 0 评论 -
快速排序(算法导论)java实现
快速排序(QuickSort)是对冒泡排序(BubbleSort)的一种改进。排序效率在同为O(N*logN)的几种排序方法中效率较高,且快速排序算法是 分治策略的典型应用。时间复杂度:O(N*logN)。版本一:算法的关键部分是Partition过程,它实现了对子数组 A[p...r] 的原址重排。/** * 快速排序一,算法导论P95 * @author Ad...原创 2019-09-23 23:52:28 · 359 阅读 · 0 评论
分享