【JavaScript】前端算法题 40道题+解析

  • 【JavaScript】前端算法题 40道题+解析已关闭评论
  • 26 次浏览
  • A+
所属分类:Web前端
摘要

最近练习了一些前端算法题,现在做个总结,以下题目都是个人写法,并不是标准答案,如有错误欢迎指出,有对某道题有新的想法的友友也可以在评论区发表想法,互相学习🤭


前言

最近练习了一些前端算法题,现在做个总结,以下题目都是个人写法,并不是标准答案,如有错误欢迎指出,有对某道题有新的想法的友友也可以在评论区发表想法,互相学习🤭

题目

题目一: 二维数组中的查找: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

function sortList(array, num) { 	// 解法一.循环indexOf查询 有返回下标,没有则返回-1 	// for (let i = 0; i < array.length; i++) { 	//     if (array[i].indexOf(num) != -1) { 	//         return console.log('有'); 	//     } 	// } 	// 解法二.嵌套循环 	// for(let i=0;i<array.length;i++){ 	//     for(let j=0;j<array[i].length;j++){ 	//         if(array[i][j]==num){ 	//             return '有' 	//         } 	//     } 	// } 	// 解法三.数组扁平化,然后indexOf查找 	let newArray = toStr(array) 	console.log(newArray) 	if (newArray.indexOf(num) != -1) { 		return console.log('有'); 	} 	return console.log('没有'); }  // 数组扁平化 function toStr(arr) { 	return arr.toString().split(',').map(item => { 		return Number(item) 	}) }  let ary = [[1, 2, 3, 4], [2, 3, 4, 5]] sortList(ary, 5) 

题目二: 替换空格: 请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为 We Are Happy.则经过替换之后的字符串为 We%20Are%20Happy

function replaceSpace(str) { 	// 解法一:暴力for循环对比 	// let newStr='' 	// for(let i=0;i<str.length;i++){ 	//     if(str[i]==' '){ 	//         newStr+='%20' 	//     }else{ 	//         newStr+=str[i] 	//     } 	// } 	// console.log(newStr) 	// return newStr  	// 解法二:split分割成数组,再进行join转字符串 	// let newStr = str.split分割成数组,再进行join转字符串(" ").join("%20"); 	// console.log(newStr) 	// return newStr 	// 解法三:正则 	// var reg = / /g; 	// let newStr=str.replace(reg, "%20"); 	// console.log(newStr) 	// return newStr } replaceSpace('We Are Happy') 

题目三:从尾到头打印链表: 输入一个链表,从尾到头打印链表每个节点的值。

思路,利用栈的特性先进后出,模拟压栈,然后再进行出栈实现

class Node { 	constructor(data) { 		this.data = data 		this.next = null 	} }  function printNode(node) { 	console.log(node) 	// 压栈实现 	let stock = new Array() 	let NodeNextElm = node 	while (NodeNextElm !== null) { 		// console.log(stock) 		stock.push(NodeNextElm.data) 		NodeNextElm = NodeNextElm.next 	} 	while (stock.length > 0) { 		console.log(stock.pop()) 	} }  const node1 = new Node(1) const node2 = new Node(2) const node3 = new Node(3) node1.next = node2 node2.next = node3 printNode(node1)  

题目四:重建二叉树: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 {1,2,4,7,3,5,6,8}和中序遍历序列 {4,7,2,1,5,3,8,6},则重建二叉树并返回。

一.

①[1,2,4,7,3,5,6,8],[4,7,2,1,5,3,8,6]-> val=>1 ->L([2,4,7],[4,7,2]) & R([3,5,6,8],[5,3,8,6]) 根节点 1 ,有左右节点

二.

①L([2,4,7],[4,7,2])-> val=>2 ->L([4,7],[4,7]) && R(null , null) 根节点2(属1的左节点) ,有左节点,无右节点

②R([3,5,6,8],[5,3,8,6])-> val=>3 ->L([5],[5]) && R([6,8],[6,8]) 根节点3(属1的右节点) ,有左右节点

三.

①L([4,7],[4,7]) ->val=>4 -> L(null , null) && R([7],[7]) 根节点4(属2的左节点) ,有右节点,无左节点

②R([6,8],[8,6]) -> val=>6 -> L([8] , [8]) && R(null , null) 根节点6(属3的右节点),有左节点,无右节点

③L([5],[5]) -> val=>5->(null,null)->终止 尾节点5(属3的左节点)

四.

①R([7],[7]) -> val=>7 ->终止 尾节点7(属4的右节点)

②L([8],[8]) -> val=>8 ->终止 尾节点8(属6的左节点)

 function rebuildBinaryTree(front, centre) { 	if (!front || front.length == 0) { 		return null; 	} 	var TreeNode = { 		val: front[0] 	}; 	for (var i = 0; i < front.length; i++) { 		//找到中序遍历根节点位置 		if (centre[i] === front[0]) { 			//对于中序遍历,根节点左边的节点位于二叉树的左边,根节点右边的节点位于二叉树的右边 			TreeNode.left = rebuildBinaryTree(front.slice(1, i + 1), centre.slice(0, i)); 			TreeNode.right = rebuildBinaryTree(front.slice(i + 1), centre.slice(i + 1)); 		} 	} 	return TreeNode; } let tree = rebuildBinaryTree([1, 2, 4, 7, 3, 5, 6, 8], [4, 7, 2, 1, 5, 3, 8, 6]) console.log(tree)  

题目五:用两个栈实现队列: 用两个栈来实现一个队列,完成队列的 Push 和 Pop 操作。

思路:使用两个数组模拟栈,一个用于push一个用于pop

let stack_push = [] let stack_pop = [] function pushData(data) { 	stack_push.push(data) } function popData() { 	if (stack_pop.length > 0) { 		console.log(stack_pop.pop()) 	} else { 		if (stack_push.length > 0) { 			while (stack_push.length > 0) { 				stack_pop.push(stack_push.pop()) 			} 			console.log(stack_pop.pop()); 		} else { 			console.log('队列为空'); 		} 	} } pushData(1) pushData(2) pushData(3) pushData(4) console.log(stack_push); console.log(stack_pop); popData() console.log(stack_push); console.log(stack_pop); pushData(5) console.log(stack_push); console.log(stack_pop); popData() popData() popData() popData() popData() console.log(stack_push); console.log(stack_pop); 

题目六:旋转数组的最小数字: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为 1。NOTE:给出的所有元素都大于 0,若数组大小为 0,请返回 0。

function revoleArray(array) { 	let min = array[0]; 	let index = 0; 	for (let i = 0; i < array.length; i++) { 		if (array[i] < min) { 			min = array[i] 			index = i 		} 	} 	let newArray = array.slice(0, index) 	let newArray2 = array.slice(index) 	return newArray2.concat(newArray) } let newArray = revoleArray([3, 4, 5, 1, 2]) console.log(newArray) 

题目七:斐波那契数列: 大家都知道斐波那契数列,现在要求输入一个整数 n,请你输出斐波那契数列的第 n 项,n<=39。

思路:斐波那契数列:[1,1,2,3,5,8,13,...] 每个数等于前两个数之和

//解法一:递归 function fbnq(n) { 	if (n <= 1) { 		return 1 	} 	return fbnq(n - 1) + fbnq(n - 2) } // 解法二:循环 function Fibonacci(n) { 	if (n <= 1) { 		return 1; 	} else { 		let before_one=0,before_two=0,result=0,List=[] 		for(let i=0;i<=n;i++){ 			before_one=List[i-1]>=0?List[i-1]:0 			before_two=List[i-2]>=0?List[i-2]:0 			result=before_one + before_two 			if(result<=1)result=1 			List.push(result) 		} 		return List[n] 	} } let a = fbnq(5) console.log(a); let b = Fibonacci(5) console.log(b); 

题目八:跳台阶: 一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。

思路:jump(1)=1 jump(2)=2 jump(3)=3 jump(4)=5 jump(5)=8 类似于斐波那契数列只不过就是前两项变为1,2

function jump(n){ 	if(n<=2){ 		return n; 	} 	return jump(n-1) + jump(n-2) } let jumpNum=jump(5) console.log(jumpNum); 

题目九:变态跳台阶: 一只青蛙一次可以跳上 1 级台阶,也可以跳上 2 级……它也可以跳上 n 级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。

思路:jump(1)=1 jump(2)=2 jump(3)=4 jump(4)=8 2的n次方

function btJump(n){ // 解法一:用位运算符       2的n次方最简单就是用位运算符 1<<n(将1左移n位数)   1:0001   2:0010  4:0100  8:1000 	// return 1<<(--n);  	// 解法二:递归 	if(n<=1){ 		return n 	}else{ 		return 2*btJump(n-1)  	} } let jumpNum=btJump(5) console.log(jumpNum); 

题目十:矩形覆盖: 我们可以用 21 的小矩形横着或者竖着去覆盖更大的矩形。请问用 n 个 21 的小矩形无重叠地覆盖一个 2*n 的大矩形,总共有多少种方法?

  function rectCover(number) { 	if (number <= 2) { 		return number; 	} else { 		return rectCover(number - 1) + rectCover(number - 2); 	} } let rectNum=rectCover(4) console.log(rectNum);  

题目十一:二进制中 1 的个数: 输入一个整数,输出该数二进制表示中 1 的个数。其中负数用补码表示。

思路:一、使用split('')将其转换为字符数组然后reduce进行累加 二、暴力for循环判断

 function countOneNum(num) { 	let count=0; 	// toString(2)转化为二进制 	// 解法一:使用split('')将其转换为字符数组然后reduce进行累加 	count = num.toString(2).split('').reduce((acc, cur) => { 		console.log(acc, cur) 		return acc + parseInt(cur) 	}, 0);  	let Binary=num.toString(2) 	// 解法二:for循环 	for(let i=0;i<Binary.length;i++){ 		if(Binary[i]==1)count++ 	} 	return count } let count = countOneNum(5) console.log(count);  

题目十二:数值的整数次方: 给定一个 double 类型的浮点数 base 和 int 类型的整数 exponent。求 base 的 exponent 次方。

 function md(base,exponent){ 	if(exponent<0){ 		if(base<0){ 			return '我也不知道怎么变负数' 		}else{ 			return 1/md(base,-exponent) 		} 	}else if(exponent==0){ 		return 1 	}else{ 		return base*md(base,exponent-1) 	} } let total=md(2.33,-5) console.log(total); 

题目十三:调整数组顺序使奇数位于偶数前面: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

思路:循环找出奇偶列表,然后concat合并

 function changeArray(array) { 	let jList = [], oList = [] 	array.forEach(item => { 		if (item % 2 == 0) { 			oList.push(item) 		} else { 			jList.push(item) 		} 	}); 	return jList.concat(oList) } let NewArray = changeArray([2, 3, 4, 5, 9, 8, 7]) console.log(NewArray); 

题目十四:链表中倒数第 k 个节点: 输入一个链表,输出该链表中倒数第 k 个结点。

思路:模拟栈将链表push进栈,随后判断k是否大于等于链表的长度,反转数组再取出下标为k-1的节点

 class Node{ 	constructor(data){ 		this.data=data 		this.next=null 	} } function getIndexNode(node,index){ 	let stack=[] 	let nextNodeElm=node 	while(nextNodeElm!=null){ 		stack.push(nextNodeElm.data) 		nextNodeElm=nextNodeElm.next 	} 	if(stack.length<index){ 		return '输入的节点请小于等于链表长度' 	} 	stack.reverse() 	return stack[index-1] } const node1=new Node(1) const node2=new Node(2) const node3=new Node(3) const node4=new Node(4) const node5=new Node(5) node1.next=node2 node2.next=node3 node3.next=node4 node4.next=node5 let node=getIndexNode(node1,5) console.log(node)  

题目十五:反转链表: 输入一个链表,反转链表后,输出链表的所有元素。

class Node { 	constructor(data) { 		this.data = data 		this.next = null 	} }  function revolveNode(node) { 	if (node == null) { 		return false; 	} 	let p1 = node, p2 = null, temp = null; 	while (p1) { 		temp = p1.next; 		p1.next = p2; 		p2 = p1; 		p1 = temp; 	} 	return p2; } const node1 = new Node(1) const node2 = new Node(2) const node3 = new Node(3) const node4 = new Node(4) const node5 = new Node(5) node1.next = node2 node2.next = node3 node3.next = node4 node4.next = node5 let node = revolveNode(node1) console.log(node) 

题目十六:合并两个排序的链表: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

class Node { 	constructor(data) { 		this.data = data 		this.next = null 	} }  function Merge(node1, node2) { 	console.log(node1, node2); 	if (node1 == null) { 		return node2; 	} else if (node2 == null) { 		return node1; 	} 	var result = {}; 	if (node1.data < node2.data) { 		result = node1; 		result.next = Merge(node1.next, node2); 	} else { 		result = node2; 		result.next = Merge(node1, node2.next); 	} 	return result; } const node1 = new Node(1) const node2 = new Node(2) const node3 = new Node(3) const node4 = new Node(4) const node5 = new Node(5) const node6 = new Node(6) const node7 = new Node(7) const node8 = new Node(8) const node9 = new Node(9) const node10 = new Node(10) node1.next = node2 node2.next = node3 node3.next = node5 node4.next = node6 node5.next = node7 node6.next = node8 node8.next = node9 node9.next = node10 let newNode=Merge(node1,node4) console.log(newNode); 

题目十七:顺时针打印矩阵: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字

例如,如果输入如下矩阵:
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
思路:依次顺序打印出第一行,然后逆时针旋转矩阵,继续打印第一行,直到完成

function rotateMatrix90Clockwise(matrix) { 	const numRows = matrix.length; 	const numCols = matrix[0].length; 	let rotatedMatrix = new Array(numCols).fill(0).map(() => new Array(numRows));  	for (let i = 0; i < numRows; i++) { 		for (let j = 0; j < numCols; j++) { 			rotatedMatrix[numCols - j - 1][i] = matrix[i][j]; 		} 	}  	return rotatedMatrix; } function printNum(array){ 	let list=array.slice(0,1)[0] 	// console.log(list); 	let newList=list.reverse() 	while(newList.length>0){ 		console.log(newList.pop()) 	} 	// console.log(newList); 	array=array.slice(1,) 	if(array.length==0){ 		return 	} 	let newArray=rotateMatrix90Clockwise(array) 	printNum(newArray) } const originalMatrix = [ 	[1, 2, 3,4], 	[5, 6,7,8], 	[9,10,11,12], 	[13,14,15,16] ];  printNum(originalMatrix);  

题目十八:定义一个栈,实现 min 函数:定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的 min 函数。

let stack_push = [] let stack_pop = [] function pushData(data) { 	stack_push.push(data) }  function popData() { 	if (stack_pop.length > 0) { 		console.log(stack_pop.pop()); 	} else { 		if (stack_push.length > 0) { 			while (stack_push.length > 0) { 				stack_pop.push(stack_push.pop()) 			} 			console.log(stack_pop.pop()); 		} else { 			console.log('空栈') 		} 	} }  function searchMin() { 	while (stack_pop.length > 0) { 		stack_push.push(stack_pop()) 	} 	let min = stack_push[0] 	for (let index = 0; index < stack_push.length; index++) { 		if (stack_push[index] < min) { 			min = stack_push[index] 		} 	} 	return min } pushData(1) pushData(2) pushData(3) pushData(0) pushData(4) let min = searchMin() console.log(min); 

题目十九:栈的压入弹出:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。

例如:序列 1,2,3,4,5 是某栈的压入顺序,序列 4,5,3,2,1 是该压栈序列对应的一个弹出序列,但 4,3,5,1,2 就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

思路:一、模拟压栈弹栈 二、直接反转数组进行pop比较

let stack_push = [] let stack_pop = [] function pushData(data) { 	stack_push.push(data) } function popData() { 	if (stack_pop.length > 0) { 		console.log(stack_pop.pop()); 	} else { 		if (stack_push.length > 0) { 			while (stack_push.length > 0) { 				stack_pop.push(stack_push.pop()) 			} 			console.log(stack_pop.pop()); 		} else { 			console.log('空栈') 		} 	} } function testStack(pushStack,popStack){ 	// 解法一:模拟压栈弹栈 	// if(pushStack.length != popStack.length){ 	//     return '不是' 	// } 	// let NewPushStack=pushStack.reverse() 	// let NewPopStack=popStack.reverse() 	// while(NewPushStack.length>0){ 	//     pushData(NewPushStack.pop()) 	// } 	// while(stack_push.length>0){ 	//     if(stack_push.pop() != NewPopStack.pop())return '不对' 	// } 	// return '正确'  	// 解法二:直接反转数组进行pop比较 	if(pushStack.length != popStack.length){ 		return '不是' 	} 	let NewPopStack=popStack.reverse() 	while(pushStack.length>0){ 		if(pushStack.pop() != NewPopStack.pop())return '不对' 	} 	return '正确' } let result=testStack([1,2,3,4,5],[5,4,3,2,1]) console.log(result); 

题目二十:复杂链表的复制:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的 head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

function copyNode(pHead){ 	console.log(pHead) 	if (!pHead) { 		return null; 	} 	// 复制头结点 	var node = new Node(pHead.data); 	node.other = pHead.other; 	// 递归其他节点 	node.next = copyNode(pHead.next); 	return node; } class Node { 	constructor(data) { 		this.data = data 		this.next = null 		this.other = null 	} } const node1 = new Node(1) const node2 = new Node(2) const node3 = new Node(3) node1.next = node2 node2.next = node3 node1.other = node2 node2.other = node3 node3.other = node1 let newNode=copyNode(node1) console.log(newNode); 

题目二十一:字符串的排列:输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串 abc,则打印出由字符 a,b,c 所能排列出来的所有字符串 abc,acb,bac,bca,cab 和 cba。输入描述:输入一个字符串,长度不超过 9(可能有字符重复),字符只包括大小写字母。

 function permute(str, left = 0, right = str.length - 1) {  //abc left 2 	console.log(left,right) 	// 如果左边界等于右边界,说明只剩下一个字符,打印它 	if (left === right) { 		console.log("结果:",str); 	} else { 		// 遍历从l到r的每个位置 		for (let i = left; i <= right; i++) { 			// 将当前位置i的字符与左边界l的字符交换 			str = swap(str, left, i); 			console.log("str:",str,"left:",left,"I:",i); 			// 递归地对剩余的子字符串进行排列(注意left+1表示排除已固定的字符) 			permute(str, left + 1, right); 			// 递归返回后,需要将字符交换回原来的位置,以便下一次循环使用原始字符串 			str = swap(str, left, i);  		} 	} }  function swap(str, i, j) { 	// 将字符串转换为字符数组 	let arr = str.split(''); 	// 解构交换元素 	[arr[i], arr[j]] = [arr[j], arr[i]]; 	// 将修改后的数组转换回字符串 	return arr.join(''); }  permute('abc');  

题目二十二:数组中出现次数超过一半的数字: 数组中有一个数字出现的次数超过数组长度的一半。请找出这个数字。例如输入一个长度为 9 的数组{1,2,3,2,2,2,5,4,2}。由于数字 2 在数组中出现了 5 次,超过数组长度的一半,因此输出 2。如果不存在则输出 0。

function moreAHalfNum(array){ 	let length=array.length 	let maxLength=Math.floor(length/2) 	let computedTotal={} 	let maxNum=null 	array.forEach(item => { 		if(computedTotal[item]){ 			computedTotal[item]++ 			if(computedTotal[item]>maxLength)maxNum=item 		}else{ 			computedTotal[item]=1 		} 	}); 	return maxNum?maxNum:0 } let num=moreAHalfNum([1,2,3,4,6,6,6,6,6]) console.log(num); 

题目二十三:最小的 K 个数:输入 n 个整数,找出其中最小的 K 个数。例如输入 4,5,1,6,2,7,3,8 这 8 个数字,则最小的 4 个数字是 1,2,3,4 。

思路:先sort排序,此时数组是从小到大排序,取前k个即可

function searchMinCountNum(array,K){ 	let NewArray=array.sort() 	return NewArray.slice(0,K) } let countNum=searchMinCountNum([2,1,8,9,6,5],3) console.log(countNum); 

题目二十四:把数组排成最小的数:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为 321323。

function PrintMinNumber(numbers) { 	numbers.sort(function (a, b) { 		var s1 = a + '' + b; 		var s2 = b + '' + a; 		for (var i = 0; i < s1.length; i++) { 			if (s1.charAt(i) > s2.charAt(i)) { 				return 1 			} else if (s1.charAt(i) < s2.charAt(i)) { 				return -1; 			}  		} 		return 1 	}) 	console.log(numbers); 	var result = ""; 	numbers.map(function (num) { 		result = result.concat(num) 	}) 	return result; } let num=PrintMinNumber([32,3,321]) console.log(num); 

题目二十五:丑数(待深入理解):把只包含质因子 2、3 和 5 的数称作丑数。例如 6、8 都是丑数,但 14 不是,因为它包含因子 7。 习惯上我们把 1 当做是第一个丑数。求按从小到大的顺序的第 N 个丑数。

function getUglyNumberSolution(index) { 	if (index == 0) return 0 	var uglys = [1]; 	var factor2 = 0, factor3 = 0, factor5 = 0; 	for (var i = 1; i < index; i++) { 		uglys[i] = Math.min(uglys[factor2] * 2, uglys[factor3] * 3, uglys[factor5] * 5) 		if (uglys[i] == uglys[factor2] * 2) factor2++; 		if (uglys[i] == uglys[factor3] * 3) factor3++; 		if (uglys[i] == uglys[factor5] * 5) factor5++; 	} 	console.log(uglys); 	return uglys[index - 1] } let count=getUglyNumberSolution(11) console.log(count); 

题目二十六:第一个只出现一次的字符:在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符,并返回它的位置。

function getFirstChar(str){ 	str=str.toUpperCase() 	let chat={} 	for (let i = 0; i < str.length; i++) { 		if(chat[str[i]]){ 			chat[str[i]]++ 		}else{ 			chat[str[i]]=1 		} 	} 	console.log(chat); 	for (let i = 0; i <= str.length; i++) { 		if(chat[str[i]]==1){ 			return str.indexOf(str[i]) +"=>"+str[i] 		} 	} 	return '无只出现一次的字符' } let index=getFirstChar('hheello') console.log(index); 

题目二十七:数组中的逆序对:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数 P。

function getReverseNum(array){ 	let count=0 	let towNum=[] 	if(array.length>1){ 		towNum=array.slice(0,2) 		console.log(towNum); 		if(towNum[0]>towNum[1]){ 			count++ 		} 		return count + getReverseNum(array.slice(2,)) 	} 	return count } let num=getReverseNum([2,1,3,4,5,4,5,4,5,4,5,4]) console.log(num); 

题目二十八:数字在排序数组中出现的次数:统计一个数字:在排序数组中出现的次数。例如输入排序数组{ 1, 2, 3, 3, 3, 3, 4, 5}和数字 3 ,由于 3 在这个数组中出现了 4 次,因此输出 4 。

function getNumFindCount(array,num){ 	let count=0 	array.forEach(item => { 		if(item==num)count++ 	}); 	return count } let count=getNumFindCount([1,2,3,3,3,4,5],3) console.log(count); 

题目二十九:数组中只出现一次的数字:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

function getOnlyOneNum(array) { 	// 因为new Set去重后返回的是一个对象Set([1,2,...]),所以要用Array.from转换为数组 	let numList = Array.from(new Set(array)) 	let onlyOneList = [] 	numList.forEach(item => { 		let count = 0 		array.forEach(item2 => { 			if (item2 == item) count++ 		}) 		if (count == 1) onlyOneList.push(item) 	}) 	console.log(onlyOneList); } getOnlyOneNum([1, 2, 2, 3, 3, 4]) 

题目三十:和为 S 的连续正数序列:小明很喜欢数学,有一天他在做数学作业时,要求计算出 9~16 的和,他马上就写出了正确答案是 100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为 100(至少包括两个数)。没多久,他就得到另一组连续正数和为 100 的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为 S 的连续正数序列?Good Luck!输出描述:输出所有和为 S 的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序。

function getTotalNum(sum) { 	if (sum < 2) return []; 	var result = []; 	var a = 0, b = 0, total = 0; 	while (a <= Math.floor(sum / 2)) { 		if (total < sum) { 			b++; 			total += b; 		} else if (total > sum) { 			total -= a 			a++; 		} else { 			var temp = []; 			for (var i = a; i <= b; i++) { 				temp.push(i) 			} 			result.push(temp) 			if (a + 1 < b) { 				total -= a; 				a++ 			} else { 				break; 			} 		} 	} 	return result; } let list=getTotalNum(100) console.log(list); 

题目三十一:和为 S 的两个数字:输入一个递增排序的数组和一个数字 S,在数组中查找两个数,是的他们的和正好是 S,如果有多对数字的和等于 S,输出两个数的乘积最小的。输出描述:对应每个测试案例,输出两个数,小的先输出。

 function totaleqNum(array, sum) { 	let list = [] 	for (let i = 0; i < array.length; i++) { 		for (let j = i + 1; j < array.length; j++) { 			if (array[i] + array[j] == sum) { 				let data = { 					list: [array[i], array[j]], 					result: array[i] * array[j] 				} 				list.push(data) 			} 		} 	} 	if (list.length > 1) { 		let min = list[0].result 		list.forEach(item => {  			if (item.result < min) { 				return item.list 			} 		}) 		return list[0].list 	}  	return list[0].list } let result=totaleqNum([1, 2, 3, 4, 5, 6], 5) console.log(result);  

题目三十二:左旋转字符串:汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列 S,请你把其循环左移 K 位后的序列输出。例如,字符序列 S=”abcXYZdef”,要求输出循环左移 3 位后的结果,即 “XYZdefabc”。

function transformStr(str,left){ 	if(left>str.length){ 		return '位移长度不能超过字符长度' 	} 	let leftStr=str.slice(left,) 	let rightStr=str.slice(0,left) 	return leftStr+rightStr } let newStr=transformStr('hello',2) console.log(newStr); 

题目三十三:翻转单词顺序列:牛客最近来了一个新员工 Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事 Cat 对 Fish 写的内容颇感兴趣,有一天他向 Fish 借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了 ,正确的句子应该是“I am a student.”。Cat 对一一的翻转这些单词顺序可不在行,你能帮助他么?

思路:split对字符串按照空格分隔成数组,然后reverse反转数组,最后join合并成字符串

function revolveStr(str){ 	return newStrList=str.split(" ").reverse().join(" ") } let newStr=revolveStr("I am a student.") console.log(newStr); 

题目三十四:1+2+3+...+n:求 1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case 等关键字及条件判断语句(A?B:C)。

function totalNum(n){ 	var sum=n; 	var a=(n>0)&&((sum+=totalNum(n-1))>0) 	return sum } let total=totalNum(3) console.log(total); 

题目三十五:把字符串转换成整数。:将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。数值为 0 或者字符串不是一个合法的数值则返回 0。输入描述:输入一个字符串,包括数字字母符号,可以为空。输出描述:如果是合法的数值表达则返回该数字,否则返回 0。

思路:循环字符串,判断每个字符是否为数字,因为不能使用字符串转换整数的库函数,所以要定义一个函数判断字符串是否在0~9之间,是即为数字。

function strToNumber(str){ 	let newStr='' 	for (let i = 0; i < str.length; i++) { 		if(isNumber(str[i])){ 			newStr+=str[i] 		} 	} 	return newStr } function isNumber(data){ 	if(data>=0 || data<=9){ 		return true 	} 	return false } let newStr=strToNumber('+2147#48^3647') console.log(newStr); 

题目三十六:数组中重复的数字:在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

思路,使用set对数组进行去重,然后对数组进行遍历,再去遍历原数组,找出数组里第一个出现重复数字,随机try catch抛出异常进行中断遍历并进行返回

function searchFirstFindTwoNum(array) { 	try { 		Array.from(new Set(array)).forEach(item => { 			let count = 0 			array.forEach(item2 => { 				if (item == item2) count++ 				if (count > 1) throw new Error(item) 			}) 		}) 	} catch (e) { 		return e.message 	} 	return '数组内无重复数字' } let number = searchFirstFindTwoNum([1, 2, 3, 3, 4, 5]) console.log(number); 

题目三十七:构建乘积数组:给定一个数组 A[0,1,...,n-1],请构建一个数组 B[0,1,...,n-1],其中 B 中的元素 B[i]=A[0]A[1]...A[i-1]A[i+1]...A[n-1]。不能使用除法。

function getTotalList(array) { 	let newArray = [] 	for (let i = 0; i < array.length; i++) { 		newArray[i] = getTotal(array) * array[i-1]-array[i+1] 		console.log(newArray[i]); 	} 	return newArray } function getTotal(array) { 	let total = 1; 	array.forEach(item => total *= item); 	return total } let newArray = getTotalList([2, 4, 6, 7, 8]) console.log(newArray); 

题目三十八:字符流中第一个不重复的字符:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符 "go" 时,第一个只出现一次的字符是 "g" 。当从该字符流中读出前六个字符 "google" 时,第一个只出现一次的字符是 "l"。 输出描述:如果当前字符流没有存在出现一次的字符,返回#字符。

思路:先对原数组进行去重获取字符列表,随后单个出现单词给个默认值为首个字符,方便后续判断,首先遍历去重后的字符数组,根据每个字符对原字符串进行遍历查询是否重复,如果出现重复且重复词与单个出现字符不一致,则证明出现首个单一字符,则抛出异常结束遍历并返回,当重复时单个出现字符为当前字符,如果是则表示前面并无单一字符,并判断当前位置是否已经遍历到最末端了,如果不是继续下一个字符的遍历,如果当前位置为字符串倒数第二的位置,则下一个字符必定为单一出现单词,则直接返回。

function searchFirstFindOneStr(str) { 	try { 		let array = Array.from(new Set(str.split(""))) 		let keyword = array[0] 		array.forEach(item => { 			let count = 0 			for (let i = 0; i < str.length; i++) { 				if (item == str[i]) count++ 				if (count > 1 && keyword != str[i]) throw new Error(keyword) 				if (count > 1 && keyword == str[i]) { 					count = 0 					if (i < str.length-1 && i < str.length - 2) keyword = str[i + 1] 					if (i == str.length - 2) throw new Error(str[str.length - 1]) 				} 			} 		}) 	} catch (e) { 		return e.message 	} 	return '#' } let str = searchFirstFindOneStr("hheello66") console.log(str); 

题目三十九:数据流中的中位数(待深入理解):如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有值排序之后位于中间的数值。如果数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。

function getCenterNum(array){ //[1,2,3,4,5] 	let index=Math.floor(array.length/2) 	let newArray=array.sort() 	if(newArray.length%2==0){ 		return (newArray[index-1]+newArray[index])/2 	}else{ 		return newArray[index] 	} } let num=getCenterNum([3,2,3,7,5,6]) console.log(num); 

题目四十:滑动窗口中的最大值(待深入理解):给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小 3,那么一共存在 6 个滑动窗口,他们的最大值分别为{4,4,6,6,6,5};

思路:针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下 6 个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
最大值分别就是每个窗口[2,3,4],[3,4,2],[4,2,6],[2,6,2],[6,2,5],[2,5,1]中元素最大的一个,即为[4,4,6,6,6,5]

function slideWindowMax(array,size){ 	let allWindows=[],allMax=[] 	while(array.length>=size){ 		allWindows.push(array.slice(0,size)) 		array=array.slice(1,) 	} 	allWindows.forEach(i => { 		let max=i[0] 		i.forEach(j=>{ 			if(j>max)max=j 		}) 		allMax.push(max) 	}); 	return allMax } let maxList=slideWindowMax([2,3,4,2,6,2,5,1],3) console.log(maxList); 

上述为个人学习整理内容,水平有限,如有错误之处,望各位园友不吝赐教!如果觉得不错,请点个赞和关注支持一下!谢谢~๑•́₃•̀๑ ❀❀❀