剑指offer JS题解
秃头指非官
学生
展开
-
剑指offer JS题解 (56)删除链表中的重复的结点
题目描述在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5解题思路这道题是将重复出现的元素(两个及以上的元素)删除掉,不同于去重,需要做一点小小的修改。做这类题目的时候注意要添加虚拟的头结点,保证头结点满足重复条件的时候能被成功的删除。Code/*function ListNode(x){ this.val = x;原创 2020-06-17 18:03:43 · 139 阅读 · 0 评论 -
剑指offer JS题解 (57)二叉树的下一个结点
题目描述给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。解题思路leetcode上好像没有相关的题目,是在牛客上做的。首先要看一下树结点的结构,是具备左右结点的指针以及指向父节点的指针(next结点)的。这就使得我们在中序遍历时可以追溯二叉树要遍历的下一个结点。那我们中序遍历的时候是怎么做的?左-中-右。现在给到一个结点pNode,它可以是在左中右这三个位置上,所以需要具体讨论。首先第一个情况:结点作为根节点,此原创 2020-06-17 14:55:18 · 204 阅读 · 0 评论 -
剑指offer JS题解 (58)对称的二叉树
题目描述请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。解题思路建议画图走一下哈哈,这道题虽然做过几遍了,但还是有点忘了。剑指offer里面提供了一道镜像二叉树,还有一道是这道对称二叉树。对称二叉树其实就是,从根节点开始,其左右子树是镜像关系,这就是对称。因此,只要嵌入之前写过的镜像二叉树的函数模块即可。这道题用递归写起来很漂亮,首先,根节点为null,是对称的。接着,对左右子树进行判断:1、假如左右子树的根节点皆为空,那么可以视原创 2020-06-17 12:41:21 · 146 阅读 · 0 评论 -
剑指offer JS题解 (30)连续子数组的最大和
题目描述HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)解题思路这是一道动态规划题目,加入用sum[i]表示以第i原创 2020-06-17 12:11:00 · 139 阅读 · 0 评论 -
剑指offer JS题解 (59)按之字形顺序打印二叉树
题目描述请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。解题思路用栈存储每一层的结点序列,根据层次的奇偶来改变下一层结点的排列顺序(从左到右或者从右到左)。Codefunction Print(pRoot){ // write code here if(!pRoot) return []; let res=[]; let stack=[pRoot]; let k原创 2020-06-17 00:08:39 · 197 阅读 · 0 评论 -
剑指offer JS题解 (60)把二叉树打印成多行
题目描述从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。解题思路用两个队列,进行层次遍历和输出。一个外部的队列存储当前层次的结点,另一个内部的临时队列存储下一层要遍历的结点。Codefunction Print(pRoot){ // write code here if(!pRoot) return []; let res=[]; let queue=[pRoot]; while(queue.length){ let new原创 2020-06-16 23:28:29 · 159 阅读 · 0 评论 -
剑指offer JS题解 (61)序列化二叉树
题目描述请实现两个函数,分别用来序列化和反序列化二叉树二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己原创 2020-06-16 22:53:49 · 143 阅读 · 0 评论 -
剑指offer JS题解 (28)数组中出现次数超过一半的数
题目描述数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。解题思路这道题非常有趣,当时尝试过哈希表统计法、排序后取中值的方式。后来发现leetcode上有一种巧解(摩尔投票法)。因为数字出现的次数大于其他数字出现次数之和,可以通过正负相抵的思想,选取一个数作为众数,当遍历过程中遇到相同的数字,则选票+1;否则选票-1,直到选票为0,选择下一个数原创 2020-05-19 23:56:45 · 773 阅读 · 0 评论 -
剑指offer JS题解 (27)字符串的排列
题目描述输入一个字符串,按字典序打印出该字符串中字符的所有排列。输入规范输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。示例输入:s = “abc”输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]解题思路我在leetcode上做这道题的时候,是用的解法三,是递归回溯的方法。实际上全排列就是一个决策问题,刻画成一颗树的话,就是每一层要选择什么字符,最后能得到多少种不同的路径。并且,由于字符是可能重复的,所以还需要进行树的剪枝。具体思路如下:原创 2020-05-19 23:55:04 · 739 阅读 · 0 评论 -
剑指offer JS题解 (26)二叉搜索树与双向链表
题目描述输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。解题思路要生成排序的双向列表,只能是中序遍历,因为中序遍历才能从小到大,所以需要递归,伪代码如下:1、从根节点出发,进入递归,给设置变量pre为null,用于相邻结点之间的连接;2、先把左子树调整为双向链表,并用pre指向最后一个节点;3、将根节点和pre连起来,形成双向的连接;4、将根节点与右子树已存在连接,只需要再去调整右子树,并让pre指向右子树最后一个结点。C原创 2020-05-17 23:20:17 · 514 阅读 · 0 评论 -
剑指offer JS题解 (25)复杂链表的复制
题目描述输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)解题思路这道题有三种解法。第一种是先拷贝节点,用next连接起来。之后从头开始遍历节点,对每个节点根据random值去寻找节点,再做连接。时间复杂度为O(n²)。第二种是使用哈希表,通过哈希表来对应拷贝前后的两个复杂链表,这样一来,就可以通过原链表的rando原创 2020-05-17 23:19:41 · 521 阅读 · 0 评论 -
剑指offer JS题解 (24)二叉树中和为某一值的路径
题目描述输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。解题思路从根节点出发,寻找一条到叶结点的路径,路径上的值之和等于输入整数。由此可以知道是树的深度遍历,并且可能存在零条,一条,多条路径,需要维护一个结果数组来记录下所有可能的路径,详细见代码。Code/* function TreeNode(x) { this.val = x; this.left = null; this.right =原创 2020-05-17 23:16:49 · 451 阅读 · 0 评论 -
剑指offer JS题解 (23)二叉搜索树的后序遍历序列
题目描述输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。解题思路由后序遍历的特点我们可以知道,数组最右边的是根节点,加上二叉搜索树BST,所以左子树上的每个结点都小于根节点,右子树上的每个结点都大于根节点。所以要判断一个序列是否是BST的后序遍历序列,可以采用递归的做法。首先对于初始序列为空,要返回false;否则进入下面的过程:1、找到最右边,作为根节点;2、通过根节点的值,找出左子树和右子原创 2020-05-17 23:16:02 · 514 阅读 · 0 评论 -
剑指offer JS题解 (22)从上到下打印二叉树
题目描述从上往下打印出二叉树的每个节点,同层节点从左至右打印。解题思路层次打印树,其实就是树的广度遍历,利用队列的FIFO的特点,从上到下从左到右打印结点。Code/* function TreeNode(x) { this.val = x; this.left = null; this.right = null;} */function PrintFromTopToBottom(root){ // write code here if(!root)原创 2020-05-17 23:15:03 · 502 阅读 · 0 评论 -
剑指offer JS题解 (21)栈的压入、弹出序列
题目描述输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。示例例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)解题思路本题只要使用一个辅助栈来模拟一下栈的压入与弹出,假如能够顺利执行完两个序列,就能证明弹出序列对应于压入序列。Codefunction IsPopOrder(pushV, pop原创 2020-05-17 10:45:30 · 595 阅读 · 0 评论 -
剑指offer JS题解 (20)包含min函数的栈
题目描述定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法。解题思路笔试很喜欢考这种自定义的栈结构,这道题要求我们多维护一个能够得到栈中所含最小元素的min()方法,且时间复杂度为O(1),所以我们需要一个辅助栈来达到这个效果。每次push的时候,只要检查压入的值是否小于等于辅助栈的栈顶值,是的话就压入,否则不做操作,相当于对普通栈进行push。这样一来,min原创 2020-05-17 10:44:39 · 492 阅读 · 0 评论 -
剑指offer JS题解 (19)顺时针打印矩阵
题目描述输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。示例例如,如果输入如下4 X 4矩阵:[ [1 2 3 4] [5 6 7 8] [9 10 11 12] [13 14 15 16] ]则依次打印出数字[1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10]。解题思路本题的难点在于打印一圈数字时,要如何分配到四个方向上面。当时在leetcode上面写这道题,尝试了很多种分配方式,关键在于每运算完一边,就要及时改变边界值,才能在满足结束条件的时候及原创 2020-05-17 10:44:01 · 504 阅读 · 0 评论 -
剑指offer JS题解 (18)二叉树的镜像
题目描述操作给定的二叉树,将其变换为源二叉树的镜像。解题思路逐层对节点的左右子树进行交换即可达到目的,这里的交换使用了解构赋值的写法。Code/* function TreeNode(x) { this.val = x; this.left = null; this.right = null;} */function Mirror(root){ // write code here if(!root) return null; [root.le原创 2020-05-17 10:42:44 · 437 阅读 · 0 评论 -
剑指offer JS题解 (17)树的子结构
题目描述输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)解题思路这也是一道递归题目,如何判断树B是不是树A的子结构:1、树A中能否找到和B的根节点的值相同的结点R;2、树A中以结点R为根节点的子树包含了和树B一样的结点。Codefunction Find(target, array){ // write code here const n=array.length, m=array[0].length; l原创 2020-05-16 23:29:40 · 476 阅读 · 0 评论 -
剑指offer JS题解 (16)合并两个排序的链表
题目描述输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。解题思路采用递归的方式会非常简洁好看,只需不断比较两个链表的头部,选择较小的结点插入新链表即可。需要注意的时候,当一个链表空了之后,只需要继续接上另一个没遍历完的链表即可。时间复杂度为O(n*2)=O(n)。Code/*function ListNode(x){ this.val = x; this.next = null;}*/function Merge(pHead1, pH原创 2020-05-16 23:28:35 · 460 阅读 · 0 评论 -
剑指offer JS题解 (15)反转链表
题目描述输入一个链表,反转链表后,输出新链表的表头。解题思路一个基础题,考察对链表的操作。伪代码:1、初始化一个空的链表头部pre,和存放剩余链表的next指针;2、用传入的链表头部参数进行链表的遍历,进行如下过程:①:用next指针指向剩余链表的头部,进行保存;②:让当前遍历到的链表结点与链表断开,再去连接链表头部pre(模仿栈的结构,以pre为底部堆叠);③:接着更新pre,让它指向当前结点;④:让链表头部参数指向下一个结点。3、返回新头部,结束程序。Codefunctio原创 2020-05-16 12:58:08 · 466 阅读 · 0 评论 -
剑指offer JS题解 (14)链表中倒数第k个结点
题目描述输入一个链表,输出该链表中倒数第k个结点。解题思路涉及到链表顺序,这道题可以用双指针来跑。让指针①先跑k-1个结点,然后指针②跟着一起跑,等指针①到链表的最后一个结点了,指针②就指向倒数第k个结点(这里认为最后一个结点是倒数第1个,所以要跑k-1个结点)。Code/*function ListNode(x){ this.val = x; this.next = null;}*/function FindKthToTail(head, k){ // write原创 2020-05-16 12:57:11 · 528 阅读 · 0 评论 -
剑指offer JS题解 (13)调整数组顺序使奇数位于偶数前面
题目描述输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。解题思路之前我是在leetcode上面做的这道题,leetcode上没有保证奇数和奇数,偶数和偶数之间的相对位置不变这个限制条件,做起来相对自由,可以用头尾双指针(对撞)交换的方式去做。但这道题在牛客上增加了这个条件,难度就上来了。解法一,我一开始做的思路是把奇数与偶数分开来,然后再合并。相当于遍历第一次划分奇数偶数,遍历第二原创 2020-05-16 12:56:37 · 1453 阅读 · 0 评论 -
剑指offer JS题解 (12)数值的整数次方
题目描述给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0。解题思路传统的做法是提取出符号位之后,while(exponent–),然后不断累乘底数,但这种做法效率较低。我们可以采用快速幂的做法来解题:快速幂,就是对指数n进行二进制化,将幂的乘法运算次数减少到O(logn)次。比如说要算a的11次方,我们只需要算a的1次方,a的2次方,a的8次方。此外,本题的细节还在于判断exponent的符号。原创 2020-05-16 12:55:42 · 484 阅读 · 0 评论 -
剑指offer JS题解 (11)二进制中1的个数
题目描述输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。解题思路既然题目提示了二进制,位运算是跑不了的,我们可以逐位与上1来得到1的个数,这样的时间复杂度是O(二进制位数),一般来说这种做法已经足够了。但这道题并不单纯,还涉及到了负数,我们知道负数的补码在进行右移位时,符号位上的1会右移,并且补上1,这样一来就会陷入死循环。这时候可以利用一种巧妙的做法:利用自身进行与运算,将时间复杂度缩小至O(1的个数)。我们可以举个例子进行运算:一个二进制数1100,从右边数起第三位是处于最右原创 2020-05-16 12:54:47 · 580 阅读 · 0 评论 -
剑指offer JS题解 (10)矩形覆盖
题目描述我们可以用2 * 1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2 * 1的小矩形无重叠地覆盖一个2 * n的大矩形,总共有多少种方法?示例n=3时,2*3的矩形块有3种覆盖方法。解题思路依然是斐波那契数列,首先考虑起始的情况:当n=1时,只有一种覆盖方法;当n=2时,可以全横或者全竖,有两种覆盖方法;当n>2时,无非就是在之前的基础上摆放横块,或者摆放竖块,来形成新的2 * n矩形。也就是说,它可以是2*(n-1)的矩形增加一个竖块,或者是2*(n-2)的矩形增加两个横块原创 2020-05-16 00:17:28 · 458 阅读 · 0 评论 -
剑指offer JS题解 (9)变态跳台阶
题目描述一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。解题思路与普通跳台阶相比,递推式变为了dp[n]=dp[1]+dp[2]+…+dp[n-1]。累加的做法是可以的,但是这道题可以通过数学归纳得出更简便的做法:dp[n]=dp[1]+dp[2]+…+dp[n-1] ①dp[n-1]=dp[1]+dp[2]+…+dp[n-2] ②①、②两式相减得到dp[n]=2*dp[n-1],其中n>1。因此我们dp[n]的结果就是2的n原创 2020-05-16 00:16:46 · 508 阅读 · 0 评论 -
剑指offer JS题解 (8)跳台阶
题目描述一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。解题思路同样是斐波那契数列,采用动态规划,只不过没有dp[0],起始是dp[1]=1和dp[2]=2。Codefunction jumpFloor(number){ // write code here let f=1,g=2; while(number!=1){ g+=f; f=g-f; numbe原创 2020-05-16 00:15:56 · 437 阅读 · 0 评论 -
剑指offer JS题解 (7)斐波那契数列
题目描述大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。n<=39解题思路可以递归或者动态规划,但递归的缺点是重复计算的部分太多了,影响效率。这里选择列出动态规划的式子求解:dp[n]=dp[n-1]+dp[n-2],编程中我们可以用两个变量来完成。Codefunction Fibonacci(n){ // write code here let f=0, g=1; while(n-原创 2020-05-16 00:15:24 · 501 阅读 · 0 评论 -
剑指offer JS题解 (6)旋转数组的最小数字
题目描述把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。示例例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。解题思路采用二分搜索的思路,可以将时间复杂度降低到O(logn)。首先分别取到数组最左和最右的元素,并在mid位置上取元素,假如array[mid]>array[right],说明mid所在的是原数组的后半原创 2020-05-16 00:14:49 · 442 阅读 · 0 评论 -
剑指offer JS题解 (5)用两个栈实现队列
题目描述用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。解题思路栈是LIFO的结构,队列是FIFO的结构,使用两个栈构建队列,则可以在push的时候,将元素存入第一个栈。当需要pop操作的时候,将第一个栈中的元素弹出并压入第二个栈,这时先前较早进入第一个栈的元素会来到第二个栈的栈顶,实现FIFO。虽然只需要实现push和pop两个函数,但实现过程中是需要注意一些细节的,具体可以根据第二个栈的状态进行划分:一、push:直接压入第一个栈就行。二、pop:1、原创 2020-05-14 23:11:53 · 409 阅读 · 0 评论 -
剑指offer JS题解 (4)重建二叉树
题目描述输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。解题思路根据数据结构的知识,前序遍历是{根节点|左子树|右子树},中序遍历是{左子树|根节点|右子树},可以发现前序遍历序列的第一个结点必然是根节点,利用这一特点,可以结合其他遍历序列来重建二叉树。构建一下伪代码:1、首先两个序列其一为空时,二叉树结点为空。原创 2020-05-14 23:11:11 · 277 阅读 · 0 评论 -
剑指offer JS题解 (3)从尾到头打印链表
题目描述输入一个链表,按链表从尾到头的顺序返回一个ArrayList。示例输入:head = [1,3,2]输出:[2,3,1]解题思路可以用栈存下节点的值,JS中有反向的栈方法可以使用(shift和unshift),unshift可以从数组头部插入元素。Code/*function ListNode(x){ this.val = x; this.next = null;}*/function printListFromTailToHead(head){ //原创 2020-05-14 23:10:18 · 120 阅读 · 0 评论 -
剑指offer JS题解 (2)替换空格
题目描述请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。解题思路可以正则表达式秒掉。或者循环查找空格位置,进行替换。Codefunction replaceSpace(str){ // write code here return str.replace(/\s/g,'%20');}运行环境:JavaScript (V8 6.0.0)运行时间:12ms占用内存原创 2020-05-14 23:09:38 · 111 阅读 · 0 评论 -
剑指offer JS题解 (1)二维数组中的查找
题目描述在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。示例现有矩阵 matrix 如下:[[1, 4, 7, 11, 15],[2, 5, 8, 12, 19],[3, 6, 9, 16, 22],[10, 13, 14, 17, 24],[18, 21, 23, 26, 30]]给定 target =原创 2020-05-14 23:08:31 · 216 阅读 · 0 评论