You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionminNumberInRotateArray(rotateArray){if(rotateArray.length==0){return0}letmin=rotateArray[0]for(letiofrotateArray){min=i<min ? i : min}returnmin}
functionConvert(root){if(root==null)returnnull;if(root.left==null&&root.right==null)returnroot;1.将左子树构造成双链表,并返回链表头节点letleft=Convert(root.left);letp=left;2.定位至左子树双链表最后一个节点while(p!=null&&p.right!=null){p=p.right;}3.如果左子树链表不为空的话,将当前root追加到左子树链表if(left!=null){p.right=root;root.left=p;}4.将右子树构造成双链表,并返回链表头节点letright=Convert(root.right);5.如果右子树链表不为空的话,将该链表追加到root节点之后if(right!=null){right.left=root;root.right=right;}returnleft!=null ? left : root;}
functionConvert(root){if(root==null)returnnull;if(root.left==null&&root.right==null){leftLast=root;最后的一个节点可能为最右侧的叶节点returnroot;}1.将左子树构造成双链表,并返回链表头节点letleft=Convert(root.left);3.如果左子树链表不为空的话,将当前root追加到左子树链表if(left!=null){leftLast.right=root;root.left=leftLast;}leftLast=root;当根节点只含左子树时,则该根节点为最后一个节点4.将右子树构造成双链表,并返回链表头节点letright=Convert(root.right);5.如果右子树链表不为空的话,将该链表追加到root节点之后if(right!=null){right.left=root;root.right=right;}returnleft!=null ? left : root;}
1 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
2 请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy,则经过替换之后的字符串为We%20Are%20Happy。
用空间换时间
节约空间,直接操作原字符串,倒序插入
3 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
方法1:使用尾递归
方法2:使用栈
4 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
先序遍历特点:第一个值是根节点
中序遍历特点:根节点左边都是左子树,右边都是右子树
思路:
首先根据根节点a将中序遍历划分为两部分,左边为左子树,右边为右子树
在左子树中根据第一条规则递归,得出左子树
在右子树中根据第一条规则递归,得出右子树
最后合成一棵树
5 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
分析:
入队:将元素进栈A
出队:判断栈B是否为空,如果为空,则将栈A中所有元素pop,并push进栈B,栈B出栈;
如果不为空,栈B直接出栈。
6 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
方法1:直接找出数组最小值
方法2:直接找出开始非递增的值. 非减排序数组的旋转数组,遍历找到第一个小于前一个数的值即为最小值
方法3:二分查找,根据中间值进行判断
中间元素大于第一个元素,则中间元素位于前面的递增子数组,此时最小元素位于中间元素的后面。我们可以让第一个指针left指向中间元素。
移动之后,第一个指针仍然位于前面的递增数组中。
中间元素小于第一个元素,则中间元素位于后面的递增子数组,此时最小元素位于中间元素的前面。我们可以让第二个指针right指向中间元素。
7 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。n<=39
方法1:正向相加,以下两种写法是一样的
方法2:使用递归(速度太慢,占用大量内存,不建议使用)
8 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
分析:同样是斐波拉契数列,但是与上述的斐波拉契数列不同
上面的为 0 | 1 1 2 3 5 ……
本题的为 0 | 1 2 3 5 8 ……
9 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
分析:f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(1) =f(n-1)+f(n-1)=2*f(n-1)
数列类似于1 2 4 8 16……
使用递归
使用位运算,报错:未通过所有的测试用例,why?
10 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
普通计算
‘>>>’是无视符号位的右移,>>右移是补符号位,所以负数补1造成死循环
利用位运算符计算
11 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
传统公式求解时间复杂度O(n)
递归,事件复杂度O(logn)
综合解法
12 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分。 并保证奇数和奇数,偶数和偶数之间的相对位置不变。
方法1:另开空间
13 输入一个链表,输出该链表中倒数第k个结点。
分析:定义两个指针快指针和慢指针,让快指针先走(k-1)步
再让快指针和慢指针同时走,快指针走完时,慢指针就到达了倒数第k个节点
14 输入一个链表,反转链表后,输出新链表的表头。
15 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
方法1:采用递归版本
方法2:采用非递归版本
比较两个链表的首结点,哪个小的的结点则合并到第三个链表尾结点,并向前移动一个结点。
步骤一结果会有一个链表先遍历结束,或者没有
第三个链表尾结点指向剩余未遍历结束的链表
返回第三个链表首结点
16 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
方法1
判断以node1为根的子树与以node2为根的子树是否完全相等
方法2:使用短路版本进行改写,方法同上,只是简化了代码,但是测试不通过?
17 操作给定的二叉树,将其变换为源二叉树的镜像。
方法1:采用递归
18 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
19 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
分析:
思路:利用一个辅助栈来存放最小值
栈 3,4,2,5,1
辅助栈 3,3,2,2,1
每入栈一次,就与辅助栈顶比较大小,如果小就入栈,如果大就入栈当前的辅助栈顶
当出栈时,辅助栈也要出栈
这种做法可以保证辅助栈顶一定都当前栈的最小值
19 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。
分析:
入栈1,2,3,4,5
出栈4,5,3,2,1
借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是1,
然后判断栈顶元素是不是出栈顺序的第一个元素,这里是4,很显然1≠4,
所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,这样循环等压栈顺序遍历完成,
如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。
测试未通过,why?
20 从上往下打印出二叉树的每个节点,同层节点从左至右打印。(层次遍历,借助队列实现)
21 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
思路:
已知条件:后序序列最后一个值为root;二叉搜索树左子树值都比root小,右子树值都比root大。
1、确定root;
2、遍历序列(除去root结点),找到第一个大于root的位置,则该位置左边为左子树,右边为右子树;
3、遍历右子树,若发现有小于root的值,则直接返回false;
4、分别判断左子树和右子树是否仍是二叉搜索树(即递归步骤1、2、3)。
方法2:
思路:找住二叉查找树的特点:左子树<根<=右子树 使用分治思想
22 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
23 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。
(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
方法2:三步走——无法测试通过
24 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
方法1:非递归版
解题思路:
1.核心是中序遍历的非递归算法。
2.修改当前遍历节点与前一遍历节点的指针指向。
方法二:递归版
解题思路:
1.将左子树构造成双链表,并返回链表头节点。
2.定位至左子树双链表最后一个节点。
3.如果左子树链表不为空的话,将当前root追加到左子树链表。
4.将右子树构造成双链表,并返回链表头节点。
5.如果右子树链表不为空的话,将该链表追加到root节点之后。
6.根据左子树链表是否为空确定返回的节点。
方法三:改进递归版
解题思路:
思路与方法二中的递归版一致,仅对第2点中的定位作了修改,
新增一个全局变量记录左子树的最后一个节点。
25 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
26 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
方法1:快速排序
先对这个数组进行排序,在已排序的数组中,位于中间位置的数字就是超过数组长度一半的那个数。
方法2:直接使用键值对存储数和出现的次数
方法3:依次循环,直接统计出出现最多的数字
26 输入n个整数,找出其中最小的K个数。
1)快排(针对找第k大的数,更快捷一些)
2)冒泡排序(测试不正确)
27 计算连续子向量的最大和(包括正数和负数)
分析:使用动态规划
F(i):以array[i]为末尾元素的子数组的和的最大值,子数组的元素的相对位置不变
F(i)=max(F(i-1)+array[i],array[i])
28 求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
最直接的方法统计
29 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.所以在这里自定义一个比较大小的函数,比较两个字符串s1, s2大小的时候,先将它们拼接起来,比较s1+s2,和s2+s1那个大,如果s1+s2大,那说明s2应该放前面,所以按这个规则,s2就应该排在s1前面。
30 把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路解析:
一个丑数一定由另一个丑数乘以2或者乘以3或者乘以5得到,那么我们从1开始乘以2,3,5,就得到2,3,5三个丑数,在从这三个丑数出发乘以2,3,5就得到4,6,10,6,9,15,10,15,25九个丑数,我们发现这种方法会得到重复的丑数,而且我们题目要求第N个丑数,这样的方法得到的丑数也是无序的。那么我们可以维护三个队列:
(1)丑数数组: 1
乘以2的队列:2
乘以3的队列:3
乘以5的队列:5
选择三个队列头最小的数2加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(2)丑数数组:1,2
乘以2的队列:4
乘以3的队列:3,6
乘以5的队列:5,10
选择三个队列头最小的数3加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(3)丑数数组:1,2,3
乘以2的队列:4,6
乘以3的队列:6,9
乘以5的队列:5,10,15
……
31 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).
暴力搜索
32 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。
思路:参考《剑指offer》用归并排序的思想, 时间复杂度O(nlogn)
function InversePairs(data) {
write code here
}
33 输入两个链表,找出它们的第一个公共结点。
/function ListNode(x){
this.val = x;
this.next = null;
}/
思路:用两个指针扫描”两个链表“,最终两个指针到达 null 或者到达公共结点。
34 统计一个数字在排序数组中出现的次数。
思路:由于数组有序,所以使用二分查找方法定位k的第一次出现位置和最后一次出现位置
35 输入一棵二叉树,求该树的深度。
**从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
/* function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
} */
方法1:采用递归实现
方法2:非递归——层次遍历(测试未通过)
36 输入一棵二叉树,判断该二叉树是否是平衡二叉树。
方法1:利用剪枝
改为从下往上遍历,如果子树是平衡二叉树,则返回子树的高度;如果发现子树不是平衡二叉树,
则直接停止遍历,这样至多只对每个结点访问一次。
测试未通过,请检查是否存在语法错误或者数组越界非法访问等情况
方法2:
测试仍然未通过,请检查是否存在语法错误或者数组越界非法访问等情况
37 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
首先:位运算中异或的性质:两个相同数字异或=0,一个数和0异或还是它本身。
当只有一个数出现一次时,我们把数组中所有的数,依次异或运算,最后剩下的就是落单的数,因为成对儿出现的都抵消了。
依照这个思路,我们来看两个数(我们假设是AB)出现一次的数组。我们首先还是先异或,剩下的数字肯定是A、B异或的结果,这个结果的二进制中的1,表现的是A和B的不同的位。
我们就取第一个1所在的位数,假设是第3位,接着把原数组分成两组,分组标准是第3位是否为1。
如此,相同的数肯定在一个组,因为相同数字所有位都相同,而不同的数,肯定不在一组。
然后把这两个组按照最开始的思路,依次异或,剩余的两个结果就是这两个只出现一次的数字。
38 有多少种连续的正数序列的和为sum(至少包括两个数)
39 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
40 对于一个给定的字符序列S,请你把其循环左移K位后的序列输出
提交未通过
41 单词顺序反转
利用反转函数
利用新数组存储反转单词
先反转整个句子,再依次反转每个单词
42 有2个大王,2个小王(一副牌原本是54张)...
随机从中抽出了5张牌,大\ 小 王可以看成任何数字, 并且A看作1, J为11, Q为12, K为13
求抽到顺子的概率
为了方便起见,你可以认为大小王是0。
思路:
满足条件:
1、max-min<5
2、除0外没有重复的数字
3、数组长度为5
43 随机指定一个数m,让编号为0的小朋友开始报数,小朋友的编号是从0到n-1.每次喊到m-1的那个小朋友要出列唱首歌并出列,再从下一个小朋友开始问最后留下的一个小朋友是谁?
问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人 继续从0开始报数。求胜利者的编号。
思路1:数学归纳法——不懂...
令f[i]表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然是f[n]。
递推公式
f[1]=0;
f[i]=(f[i-1]+m)%i; (i>1)
思路2:用数组模拟环——不懂...
44 求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
共同点:一,利用利用短路 && 来实现 if的功能;二,利用递归来实现循环while的功能
不同点:方法一:递归实现1+2+..+n;方法二:n(n+1)/2,递归实现n(n+1);方法三,利用Math实现n(n+1)
思路1:递归实现1+2+..+n
思路2: n(n+1)/2,递归实现n(n+1);
思路3,利用Math实现n(n+1)
45 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
首先看十进制是如何做的: 5+7=12,三步走
第一步:相加各位的值,不算进位,得到2。
第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。
第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。
同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111 第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。
第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。
第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。
继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。
46 将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。
以下算法测试不通过,如输入+123,输出为0
47 在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
思路1:
最简单的方法:我最直接的想法就是构造一个容量为N的辅助数组B,原数组A中每个数对应B中下标,首次命中,B中对应元素+1。如果某次命中时,B中对应的不为0,
说明,前边已经有一样数字了,那它就是重复的了。
时间复杂度O(n),空间复杂度O(n),算法优点是简单快速,比用set更轻量更快,不打乱原数组顺序。
时间O(n), 空间O(1)_这个看不太懂...
The text was updated successfully, but these errors were encountered: