1.二叉树的深度
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
//DFS,递归
function TreeDepth(pRoot)
{
if (pRoot==null){
return 0;
}
let leftheight=TreeDepth(pRoot.left);
let rightheight=TreeDepth(pRoot.right);
return Math.max(leftheight,rightheight)+1;
}
//BFS
function TreeDepth(pRoot)
{
let level=0;
if (pRoot==null){
return 0;
}
let queue=[pRoot];
while(queue.length!=0){
let len=queue.length;
while(len--){//遍历每一层
let cur=queue.shift();
if(cur.left!=null){
queue.push(cur.left);
}
if(cur.right!=null){
queue.push(cur.right);
}
}
level++;
}
return level;
}
2.数组中重复的数字
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
function duplicate(numbers, duplication)
{
if(numbers==null){
return false;
}
let count=new Array(1000).fill(0);
for(let i=0;i
3.求1+2+3+…+n
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
function Sum_Solution(n)
{
let sum=Math.pow(n,2)+n;
return sum>>1;//右移相当于除以2
}
4.剪绳子
给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
/**
* 题目分析:
* 先举几个例子,可以看出规律来。
* 4 : 2*2
* 5 : 2*3
* 6 : 3*3
* 7 : 2*2*3 或者4*3
* 8 : 2*3*3
* 9 : 3*3*3
* 10:2*2*3*3 或者4*3*3
* 11:2*3*3*3
* 12:3*3*3*3
* 13:2*2*3*3*3 或者4*3*3*3
*
* 下面是分析:
* 首先判断k[0]到k[m]可能有哪些数字,实际上只可能是2或者3。
* 当然也可能有4,但是4=2*2,我们就简单些不考虑了。
* 5<2*3,6<3*3,比6更大的数字我们就更不用考虑了,肯定要继续分。
* 其次看2和3的数量,2的数量肯定小于3个,为什么呢?因为2*2*2<3*3,那么题目就简单了。
* 直接用n除以3,根据得到的余数判断是一个2还是两个2还是没有2就行了。
* 由于题目规定m>1,所以2只能是1*1,3只能是2*1,这两个特殊情况直接返回就行了。
function cutRope(number)
{
if(number===2) return 1;
if(number===3) return 2;
let a=Math.floor(number/3),b=number%3;
switch(b){
case 0:return Math.pow(3,a);
case 1:return Math.pow(3,a-1)*4;
case 2:return Math.pow(3,a)*2;
}
}
5.把二叉树打印成多行
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
/* function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
} */
function Print(pRoot)
{
if(pRoot==null){
return [];
}
let queue=[pRoot];
let que=[];
while(queue.length){
let len=queue.length;
var temp=[];
while(len--){
let cur=queue.shift();
temp.push(cur.val);
if(cur.left!=null){
queue.push(cur.left);
}
if(cur.right!=null){
queue.push(cur.right);
}
}
que.push(temp);
}
return que;
}
6.二叉树的镜像
操作给定的二叉树,将其变换为源二叉树的镜像。
/* function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
} */
function Mirror(root)
{
if(root===null){
return null;
}
let temp = root.left;
root.left = root.right;
root.right =temp;
Mirror(root.left);
Mirror(root.right);
}
7.变态跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
function jumpFloorII(number)
{
if(number==1){
return 1;
}else{
return jumpFloorII(number-1)*2;
}
}
8.两个栈来实现一个队列
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
var stack1=[],stack2=[];
function push(node)
{
stack1.push(node);
}
function pop()
{
if(stack2.length==0){
if(stack1.length==0){
return null;
}else{
while(stack1.length!=0){
stack2.push(stack1.pop());
}
}
return stack2.pop();
}else{
return stack2.pop();
}
}
9.整数中1出现的次数
求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
function NumberOf1Between1AndN_Solution(n)
{
let num=0;
for(let i=1;i<=n;i++){
i.toString().split('').forEach( item=>{
if(item=='1'){
num++;
}
})
}
return num;
}
10.旋转数组的最小数字
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
function minNumberInRotateArray(rotateArray)
{
if(rotateArray.length==0){
return 0;
}
for(let i=0;i
11.数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
var arr=[];
function Insert(num)
{
arr.push(num);
for(let i=arr.length-2;arr[i]>num;i--){
[arr[i],arr[i+1]]=[arr[i+1],arr[i]];
}
}
function GetMedian(){
if(arr.length%2===1){
return arr[(arr.length-1)/2];
}else{
return (arr[arr.length/2]+arr[arr.length/2-1])/2;
}
}
12.矩形覆盖
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
function rectCover(number)
{
if(number==0||number==1||number==2){
return number;
}else{
return rectCover(number-1)+rectCover(number-2);
}
}
13.跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
function jumpFloor(number)
{
if(number<=2){
return number;
}else{
return jumpFloor(number-1)+jumpFloor(number-2);
}
}
14.和为S的连续正数序列
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
function FindContinuousSequence(sum)
{
if(sum==0){
return 0;
}
let arr=[];
for(let i=1;i<=Math.ceil(sum/2);i++){
let total=0;
let count=0;
for(let j=i;jsum){
break;
}
}
}
return arr;
}
15.数值的整数次方
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0
function Power(base, exponent)
{
let cal=1;
if(exponent==0){
return 1;
}
else if(exponent>0){
for(let i=0;i
16.二进制中1的个数
输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。
function NumberOf1(n)
{
let flag=1,count=0;
while(flag){
if(flag&n){
count++;
}
flag=flag<<1;
}
return count;
}
17.和为S的两个数
function FindNumbersWithSum(array, sum)
{
let left=0;
let right=array.length-1;
let arr=[];
let min=[];
while(left
18.数组中只出现一次的数字
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
function FindNumsAppearOnce(array)
{
let n=array.length;
let list=[];
let acount=new Array(1000).fill(0);
for(let i=0;i
19.数字在排序数组中出现的次数
统计一个数字在排序数组中出现的次数。
function GetNumberOfK(data, k)
{
let count=0;
let i=data.indexOf(k);
while(data[i]==k){
count++;
i++;
}
return count;
}
20.连续子数组的最大和
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)
function FindGreatestSumOfSubArray(array)
{
let mem=[array[0]];
let max=array[0];
for(let i=1;i
21.数组中有一个数字出现的次数超过数组长度的一半
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
function MoreThanHalfNum_Solution(numbers)
{
let n=Math.floor(numbers.length/2);
let list=new Set(numbers);
let lists = Array.from(list);
for(var i=0;in){
return lists[i];
break;
}
}
return 0;
}
22.字符流中第一个只出现一次的字符
题目描述
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:
如果当前字符流没有存在出现一次的字符,返回#字符。
//Init module if you need
let map={};
function Init()
{
map={};
}
//Insert one char from stringstream
function Insert(ch)
{
map[ch]=map[ch]?map[ch]+1:1;
}
//return the first appearence once char in current stringstream
function FirstAppearingOnce()
{
for(let i in map){
if(map[i]===1){
return i;
break;
}
}
return '#';
}
23.表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。
//s字符串
function isNumeric(s)
{
return !isNaN(s);
}
24.扑克牌顺子
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。
function IsContinuous(numbers)
{
if(numbers.length!=5){
return false;
}
let count=0;
let dis=0;
numbers.sort((a,b)=>a-b);
for(let i=0;icount;i--){
dis+=numbers[i]-numbers[i-1]-1;
if(numbers.indexOf(numbers[i])!=i){
return false;
}
}
if(count
25.左旋转字符串
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
function LeftRotateString(str, n)
{
if(!str||str.length==0){
return '';
}
n=n%str.length;
return str.slice(n)+str.slice(0,n);
}
26.链表中环的入口结点
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function EntryNodeOfLoop(pHead)
{
if(!pHead){
return null;
}
let arr=[];
let temp=pHead;
while(temp){
if(arr.indexOf(temp)!=-1){
return temp;
}else{
arr.push(temp);
temp=temp.next;
}
}
return null;
}
27.孩子们的游戏(圆圈中最后剩下的数)
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
如果没有小朋友,请返回-1
function LastRemaining_Solution(n, m)
{
if(n<=0||m<1){
return -1;
}
let children=[];
for(let i=0;i1){
del=(del+m-1)%children.length;
children.splice(del,1);
}
return children[0];
}
28.两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function FindFirstCommonNode(pHead1, pHead2)
{
if(pHead1==null||pHead2==null){
return null;
}
let node1=pHead1;
let node2=pHead2;
let arr=[];
while(node1){
arr.push(node1);
node1=node1.next;
}
while(node2){
if(arr.indexOf(node2)!=-1){
return node2;
}
node2=node2.next;
}
return null;
}
29.合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function Merge(pHead1, pHead2)
{
if(pHead1 === null) return pHead2;
else if(pHead2 === null) return pHead1;
let node1=pHead1;
let node2=pHead2;
if(node1.val<=node2.val){
var merge=node1;
var root=merge;
node1=node1.next;
}
else{
var merge=node2;
var root=merge;
node2=node2.next;
}
while(node1!=null&&node2!=null){
if(node1.val<=node2.val){
merge.next=node1;
merge=merge.next;
node1=node1.next;
}else{
merge.next=node2;
merge=merge.next;
node2=node2.next;
}
}
if(node1==null){
while(node2!=null){
merge.next=node2;
merge=merge.next;
node2=node2.next;
}
}
else{
while(node1!=null){
merge.next=node1;
merge=merge.next;
node1=node1.next;
}
}
return root;
}
30.反转链表
输入一个链表,反转链表后,输出新链表的表头。
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function ReverseList(pHead)
{
let arr=[];
let node1=pHead;
let cur=pHead;
let res=cur;
while(node1!=null){
arr.push(node1.val);
node1=node1.next;
}
arr.reverse();
for(let i=0;i
31.二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
/* function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
} */
function Convert(pRootOfTree)
{
if(!pRootOfTree){
return null;
}
let stack=[];
let p=pRootOfTree;
let isFirst=true;
var pre,first,last;
while(p!=null||stack.length>0){
while(p){
stack.push(p);
p=p.left;
}
p=stack.pop();
if(isFirst){
first=p;
pre=p;
isFirst=false;
}
else{
p.left=pre;
pre.right=p;
pre=p;
}
p=p.right;
}
return first;
}
32.二叉树的下一个结点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
/*function TreeLinkNode(x){
this.val = x;
this.left = null;
this.right = null;
this.next = null;
}*/
//1、有右子树的,那么下个结点就是右子树最左边的点;(eg:D,B,E,A,C,G) ,那么父节点就是下一个节点 ;
// 2、没有右子树的,也可以分成两类,
//a)是父节点左孩子(eg:N,I,L)
//b)是父节点的右孩子(eg:H,J,K,M)找他的父节点的父节点的父节点...直到当前结点是其父节点的左孩子位置(数拐弯的位置)_。如果没有eg:M,那么他就是尾节点。
function GetNext(pNode)
{
if(pNode==null){//空树
return null;
}
let p=pNode;
if(p.right){//有右子树
p=p.right;
while(p.left){
p=p.left;
}
return p;
}
else{//没有右子树
if(p.next&&p.next.left==pNode){//是父节点左孩子
return p.next;
}
while(p.next){//是父节点右孩子
p=p.next;
if(p.next&&p.next.left==p){
return p.next;
}
}
}
return null;//树最后一个节点
}
33.平衡二叉树
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
/* function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
} */
function IsBalanced_Solution(pRoot)
{
if(pRoot==null){
return true;
}
let l1=treeDepth(pRoot.left);
let l2=treeDepth(pRoot.right);
let cal=Math.abs(l1-l2);
if(cal<=1){
return true;
}
return false;
}
function treeDepth(pRoot){
if(pRoot==null){
return 0;
}
let leftDepth=treeDepth(pRoot.left);
let rightDepth=treeDepth(pRoot.right);
return Math.max(leftDepth,rightDepth)+1;
}
34.重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
/* function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
} */
function reConstructBinaryTree(pre, vin)
{
let res={};
if(pre.length==0){
return null;
}
if(pre.length==1){
res.val=pre[0];
res.left=null;
res.right=null;
}else{
let root=pre[0];
let index=vin.indexOf(root);
let vin1=vin.slice(0,index);
let vin2=vin.slice(index+1,vin.length);
pre.shift();
let pre1=pre.slice(0,vin1.length);
let pre2=pre.slice(vin1.length,pre.length);
res.val=root;
res.left=reConstructBinaryTree(pre1, vin1);
res.right=reConstructBinaryTree(pre2, vin2);
}
return res;
}