最近练习了一些前端算法题,现在做个总结,以下题目都是个人写法,并不是标准答案,如有错误欢迎指出,有对某道题有新的想法的友友也可以在评论区发表想法,互相学习🤭
前言
最近练习了一些前端算法题,现在做个总结,以下题目都是个人写法,并不是标准答案,如有错误欢迎指出,有对某道题有新的想法的友友也可以在评论区发表想法,互相学习🤭
题目
题目一: 二维数组中的查找: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
function sortList (array, num ) {
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 ) {
}
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 ) {
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 ){
if (n<=1 ){
return n
}else {
return 2 *btJump (n-1 )
}
}
let jumpNum=btJump (5 )
console .log (jumpNum);
题目十:矩形覆盖: 我们可以用 21 的小矩形横着或者竖着去覆盖更大的矩形。请问用 n 个 2 1 的小矩形无重叠地覆盖一个 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 ;
count = num.toString (2 ).split ('' ).reduce ((acc, cur ) => {
console .log (acc, cur)
return acc + parseInt (cur)
}, 0 );
let Binary =num.toString (2 )
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 ]
let newList=list.reverse ()
while (newList.length >0 ){
console .log (newList.pop ())
}
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 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 ) {
console .log (left,right)
if (left === right) {
console .log ("结果:" ,str);
} else {
for (let i = left; i <= right; i++) {
str = swap (str, left, i);
console .log ("str:" ,str,"left:" ,left,"I:" ,i);
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 ) {
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 ){
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);
上述为个人学习整理内容,水平有限,如有错误之处,望各位园友不吝赐教!如果觉得不错,请点个赞和关注支持一下!谢谢~๑•́₃•̀๑ \❀❀❀
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体