面对薄弱的算法,在此定一个flag,2021年实现300道+算法题,以此记录 时间2021-01-01 23:36:55开始
递归相关练习
1、commentId 为空代表一级 不为空会等于上一条的_id 实现树状结构 代码如下
/** * @description * @author cq * @Date 2021-01-01 22:48:23 * @LastEditTime 2021-01-01 23:39:05 * @LastEditors cq */ // commentId 代表一级 不为空会等于上一条的_id // 怎么 按照 h1 h2 h3的这种层级顺序渲染出来 const arr = [ { commentId: "98bb04175fef248a00f405f81c80d217", createTime: "2021-01-01 13:33:55", questionId: "a8831daa5fec73020126af6b2940f269", text: "回复1-1的1-1-2", user_id: "o2ml-5c_nKI2Tf9pLBJBCdnbu5v4", _id: "85ff8afa5fef24c401285c05361e3a60", }, { commentId: "98bb04175fef248a00f405f81c80d217", createTime: "2021-01-01 13:33:35", questionId: "a8831daa5fec73020126af6b2940f269", text: "回复1-1的1-1-1", user_id: "o2ml-5c_nKI2Tf9pLBJBCdnbu5v4", _id: "2424fa985fef24af0106b8f77f917199", }, { commentId: "2f6ab8515fef247600ebabef520933ce", createTime: "2021-01-01 13:33:13", questionId: "a8831daa5fec73020126af6b2940f269", text: "回复第三条3-1", user_id: "o2ml-5c_nKI2Tf9pLBJBCdnbu5v4", _id: "9f2a34705fef2499012c075e4669fe44", }, { commentId: "2f6ab8515fef246400ebab0350bf130a", createTime: "2021-01-01 13:32:58", questionId: "a8831daa5fec73020126af6b2940f269", text: "回复第一条1-1", user_id: "o2ml-5c_nKI2Tf9pLBJBCdnbu5v4", _id: "98bb04175fef248a00f405f81c80d217", }, { commentId: "", createTime: "2021-01-01 13:32:38", questionId: "a8831daa5fec73020126af6b2940f269", text: "我是第三条", user_id: "o2ml-5c_nKI2Tf9pLBJBCdnbu5v4", _id: "2f6ab8515fef247600ebabef520933ce", }, { commentId: "", createTime: "2021-01-01 13:32:30", questionId: "a8831daa5fec73020126af6b2940f269", text: "我是第二条评论", user_id: "o2ml-5c_nKI2Tf9pLBJBCdnbu5v4", _id: "98bb04175fef246e00f4046a439f441b", }, { commentId: "", createTime: "2021-01-01 13:32:20", questionId: "a8831daa5fec73020126af6b2940f269", text: "我是第一条评论", user_id: "o2ml-5c_nKI2Tf9pLBJBCdnbu5v4", _id: "2f6ab8515fef246400ebab0350bf130a", }, ] function deep(array = [], commentId = "", newArr = []) { let arr = array.filter(item => item.commentId == commentId); for (let index = 0; index < arr.length; index++) { const element = arr[index]; newArr.push({ item: element, children: [] }); //第一次把第一条评论放进来 const downObj = array.find(item => item.commentId == newArr[newArr.length - 1].item._id); if (downObj) { deep(array, element._id, newArr[index].children) } else { continue } } return newArr } console.log(deep(arr, "", []), "deep")
2、实现数字的阶乘
/** * @description * @author cq * @Date 2021-01-03 19:59:32 * @LastEditTime 2021-01-03 20:03:17 * @LastEditors cq */ /* 使用递归 求n的阶乘 假设 写好了一个函数 factorial 1:1 2:1*2 ->fn(1)*2 3:1*2*3 ->fn(2)*3 4:1*2*3*4 ->fn(3)*4 ... n:1*2*3...*n ->factorial(n-1)*n */ const factorial=(n)=>{ // 条件是 if (n == 1) { return 1; } return factorial(n - 1) * n; } console.log(factorial(2)); console.log(factorial(3)); console.log(factorial(4)); console.log(factorial(100));
3、求两个数的最大公约数
/** * @description 求两个数最大公约数 * @author cq * @Date 2021-01-05 17:26:05 * @LastEditTime 2021-01-05 17:51:42 * @LastEditors cq */ /* 例:48, 57 57 % 48=9 大数对小数求余 48 % 9=3 小数对上次的余数求余,重复这个过程直到余数为0 9 % 3=0 余数为0时,此次求余的小数就是最大公约数 */ //功能:求两个数的最大公约数 //参数:两个数: //返回值:最大公约数 // max 是大数 min 是小数 const commonDivisor = (min, max) => { if (max % min) { return commonDivisor(max % min, min) } else { return min } } console.log(commonDivisor(9, 12)) console.log(commonDivisor(4, 2)) console.log(commonDivisor(49, 7)) console.log(commonDivisor(16, 12))
4、求前一百的和
/** * @description 求和 * @author cq * @Date 2021-01-05 19:52:33 * @LastEditTime 2021-01-05 20:14:41 * @LastEditors cq */ // 求前一百的和 const add=(num)=>{ if(num==1){ return 1 } return add(num - 1) + num } console.log(add(100));
5、青蛙跳问题
/** * @description 青蛙跳 * @author cq * @Date 2021-01-08 16:03:23 * @LastEditTime 2021-01-08 16:34:54 * @LastEditors cq */ // 一只青蛙一次可以跳上1级台阶,也可以跳上2级。 // 求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。 // 1-1 // 4-5 // 1 - 1 - 1 - 1 // 2 - 2 // 1 - 2 - 1 // 1 - 1 - 2 // 2 - 1 - 1 let reccord = {}; function jumpFloor(number) { // 开局要么先跳1要么2 if (number === 1) { return 1 } if (number === 2) { return 2 } console.log(reccord, "reccord"); if (reccord[number]) { //最小肯定是3开始计数 return reccord[number] } let res = jumpFloor(number - 1) + jumpFloor(number - 2); console.log(res, "res", reccord); reccord[number] = res console.log(reccord, "--"); return res } console.log(jumpFloor(5));
数组相关练习
6、求任意两数之和在数组中查找
/** * @description 求任意数组中的两项之和 * @author cq * @Date 2021-01-08 16:40:32 * @LastEditTime 2021-01-08 17:35:01 * @LastEditors cq */ /* 给出一个整数数组,请在数组中找出两个加起来等于目标值的数, 你给出的函数twoSum 需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2.。注意:下标是从1开始的 假设给出的数组中只存在唯一解 例如: 给出的数组为 [20, 70, 110, 150] , 目标值为90 输出 index1 = 1, index2 = 2 */ // 79ms const twoSum1 = (numbers, target) => { for (let index = 0; index < numbers.length; index++) { const element = numbers[index]; let findIndex = numbers.findIndex((item, i) => item === (target - element) && i != index); //循环太多余 if (findIndex != -1) { return [index + 1, findIndex + 1] } } } // 46ms const twoSum = (numbers, target) => { const map = new Map(); for (let i = 0; i < numbers.length; i++) { console.log("进来几次", numbers[i]); // 初始话的map肯定是个空的 // 第二次进来的就不是3了 而是第二次循环的2 所以对比之下就能排除了我们写的那个排除自身的逻辑了 if (map.has(target - numbers[i])) { return [map.get(target - numbers[i]) + 1, i + 1] } else { // 第一次将3放进去 和他的下标i map.set(numbers[i], i) } } } console.log(twoSum([3, 2, 4], 6)); //[2,3] // console.log(twoSum([0, 4, 3, 0], 0)); //[ 1, 4 ]
7、数组的奇偶性分离
/** * @description 数组奇偶性分离 * @author cq * @Date 2021-01-08 17:40:46 * @LastEditTime 2021-01-11 10:18:59 * @LastEditors cq */ /* 输入一个整数数组,实现一个函数来调整该数组中数字的顺序, 使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分, 并保证奇数和奇数,偶数和偶数之间的相对位置不变。 */ function reOrderArray(array) { let arr1=[] let arr2=[] for (let index = 0; index < array.length; index++) { const element = array[index]; if (element%2){ // 奇数 arr1.push(element) }else{ arr2.push(element) } } return [...arr1,...arr2] } console.log(reOrderArray([1,2,3,4,5,6,7,9,8]));
8、加起来的值为目标值的组合
/** * @description 加起来的值为目标值的组合 * @author cq * @Date 2021-01-11 10:39:34 * @LastEditTime 2021-01-11 14:56:15 * @LastEditors cq */ // function duplicate(array) { // let arr = [] // for (let index = 0; index < array.length; index++) { // const element = array[index]; // arr.push(element.sort().join(",")) // } // return [...new Set(arr)] // } // function deep(num, target, arr) { // for (let index = 0; index < num.length; index++) { // const element = num[index]; // // 第一次循环把直接两数相加等于目标值的数找出来 // const i = num.indexOf(target - element); // if (i != -1) { // arr.push([element, num[i]]); // } else { // return deep(num, target - element) // } // } // return arr // } // function combinationSum2(num, target) { // let arr=[]; // for (let index = 0; index < num.length; index++) { // const element = num[index]; // // 第一次循环把直接两数相加等于目标值的数找出来 // const i = num.indexOf(target - element); // if (i!=-1){ // arr.push([element, num[i]]); // }else{ // deep(num, target - element, arr) // } // } // return duplicate(arr).map(item=>item.split(",")) // } function combinationSum2(num, target) { num.sort((a, b) => a - b); let res = []; //最终结果 let temp = []; find(num, 0, target, temp, res); return res; } function find(num, start, target, temp, res) { // 当目标值减到0了就终止整个递归 if (target == 0) { res.push([...temp]); return; } // target >= num[i] 如果目标值不如当前值大了就没有意思了 for (let i = start; i < num.length && target >= num[i]; i++) { // 当下标大于0的时候且上一项与当前项相等的时候直接跳过 console.log(i, start,"i, start"); if (i > start && num[i] == num[i - 1]) { continue; } temp.push(num[i]); //依次push 10-10-20-50 不合适-50 (10-10-20)再进去此时start保留在了3 不合适-20 再往后 加60合适 console.log(temp, "temp-start"); find(num, i + 1, target - num[i], temp, res); console.log(temp,"temp"); temp.pop(); console.log(temp, "pop"); } } // [100,10,20,70,60,10,50],80 console.log(combinationSum2([100, 10, 20, 70, 60, 10, 50], 80)); // 返回 [[10,10,60],[10,20,50],[10,70],[20,60]]
9、数组中相加和为0的三元组
/** * @description 数组中相加和为0的三元组 * @author cq * @Date 2021-01-11 15:07:04 * @LastEditTime 2021-01-11 16:20:25 * @LastEditors cq */ function threeSum(num) { let temp = []; let res = []; num.sort((a, b) => a - b); find(num, 0, temp, res); return res function find(num, start, temp, res) { if (temp.length == 3) { const [a, b, c] = temp; if (a + b + c == 0) { res.push([...temp]) return } } for (let index = start; index < num.length; index++) { const element = num[index]; // 主要目的就是去重 if (index > start && element == num[index - 1]) { continue } temp.push(element) find(num, index + 1, temp, res) temp.pop() } } } function threeSum1(num) { // write code here num.sort((a, b) => a - b) let res = [], len = num.length for (let i = 0; i < len - 2; i++) { let j = i + 1, k = len - 1 // k , j 分别表示尾部开始的最后一项和当前想的下一项 if (i == 0 || num[i] != num[i - 1]) { while (k > j) { if (num[i] + num[j] + num[k] == 0) { // 满足条件 直接放进 res.push([num[i], num[j], num[k]]) // 头部去重(如果后面一个数跟当前的数字相等,则代表有重复的结果生成,跳过) while (j + 1 < k && num[j + 1] === num[j]) j++; // 尾部去重(如果前面一个数跟当前的数字相等,则代表有重复的结果生成,跳过) while (k - 1 > j && num[k - 1] === num[k]) k--; k--; j++ } else if (num[i] + num[j] + num[k] > 0) { // 因为当前数组是按照从小到大排序的 所以如果三项大于0 肯定越往后越大于0 // 反之一样 k-- } else if (num[i] + num[j] + num[k] < 0) { j++ } } } } return res } console.log(threeSum([-2, 0, 1, 1, 2, -3, -4, 3, 4,-3,3]), "threeSum"); //[[-2,0,2],[-2,1,1]] console.log(threeSum1([-2, 0, 1, 1, 2, -3, -4, 3, 4,-3,3]), "threeSum1"); //[[-2,0,2],[-2,1,1]]
10、数组中未出现的最小正整数
/** * @description 数组中未出现的最小正整数 * @author cq * @Date 2021-01-11 16:40:05 * @LastEditTime 2021-01-11 17:08:54 * @LastEditors cq */ /* 给定一个无序数组arr,找到数组中未出现的最小正整数 例如arr = [-1, 2, 3, 4]。返回1 arr = [1, 2, 3, 4]。返回5 [要求] 时间复杂度为O(n)O(n),空间复杂度为O(1)O(1) */ // 废柴 错误 function minNumberdisappered(arr) { arr.sort((a, b) => a - b); let i = 0 while (i < arr.length) { if (arr[i] >= 0) { // 从大于0的时候开始计算 if ((arr[i] + 1) != arr[i + 1]) { return arr[i] + 1 } } else { if (arr[i + 1] > 0) { return arr[i + 1] - 1 } } i++ } } // 经典35 正确 function minNumberdisappered1(arr) { // write code here const len = arr.length for (let i = 1; i <= len; i++) { if (arr.indexOf(i) === -1) { return i } } return len + 1 } console.log(minNumberdisappered([-1, 2, 3, 4])); //1 console.log(minNumberdisappered([1, 2, 3, 4])); //5 console.log(minNumberdisappered([-1, 200, 300, 450]), "minNumberdisappered"); console.log(minNumberdisappered1([-1, 200, 300, 450]),"minNumberdisappered1");
11、从0,1,2,...,n这n+1个数中选择n个数,组成有序数组,找出这n个数中缺失的那个数
/** * @description 缺失数 * @author cq * @Date 2021-01-11 17:27:21 * @LastEditTime 2021-01-11 17:31:32 * @LastEditors cq */ /* 从0,1,2,...,n这n+1个数中选择n个数,组成有序数组, 找出这n个数中缺失的那个数,要求O(n)尽可能小。 */ function solve(a) { for (let index = 0; index < a.length; index++) { const element = a[index]; if ((element + 1) != a[index+1]){ return element + 1 } } } function solve1(a) { let index = 0 while (a[index] + 1 === a[index + 1]) { index++ } return a[index] + 1 } function solve2(a) { // write code here let left = 0, right = a.length while (left < right) { const mid = left + Math.floor((right - left) / 2) if (a[mid] === mid) { left = mid + 1 } else if (a[mid] > mid) { right = mid } } return left } console.log(solve([0, 1, 2, 3, 4, 5, 7])); //6
13、数组中只出现一次的数字
/** * @description 数组中只出现一次的数字 * @author cq * @Date 2021-01-13 20:18:49 * @LastEditTime 2021-01-13 20:28:53 * @LastEditors cq */ function FindNumsAppearOnce(array) { // write code here let res = []; for (let index = 0; index < array.length; index++) { const element = array[index]; const arr = array.filter(el => el == element); if (arr.length == 1) { res.push(arr[0]) } else { continue } } return res } function FindNumsAppearOnce1(array) { // write code here // return list, 比如[a,b],其中ab是出现一次的两个数字 let arrObj = {} for (let i = 0; i < array.length; i++) { let stringItem = array[i].toString() let temp = arrObj[stringItem] if (temp) { delete arrObj[stringItem] } else { arrObj[stringItem] = 1 } } return Object.keys(arrObj) } console.log(FindNumsAppearOnce([2, 4, 3, 6, 3, 2, 5, 5])); console.log(FindNumsAppearOnce1([2, 4, 3, 6, 3, 2, 5, 5]),"FindNumsAppearOnce1");
14、数组中的某一个数字超过了数组长度的一半
/** * @description 数组中的某一个数字超过了数组长度的一半 * @author cq * @Date 2021-01-13 20:33:45 * @LastEditTime 2021-01-13 20:44:39 * @LastEditors cq */ /* 数组中有一个数字出现的次数超过数组长度的一半, 请找出这个数字。例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。 由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 */ function MoreThanHalfNum_Solution(numbers) { // write code here let res = 0 for (let index = 0; index < numbers.length; index++) { const element = numbers[index]; const arr = numbers.filter(el => el == element); if (arr.length > (numbers.length / 2)) { res = arr[0] } else { continue } } return res } // 真尼玛牛逼 function MoreThanHalfNum_Solution1(arr) { let sortArr = arr.sort() let count = 0; let midNum = sortArr[Math.floor(sortArr.length / 2)] console.log(midNum); for (let i = 0; i < arr.length; i++) { if (arr[i] === midNum) { count++ } } return count > Math.floor(sortArr.length / 2) ? midNum : 0 } console.log(MoreThanHalfNum_Solution([2, 2, 2, 2, 2, 1, 3, 4, 5])); //2 console.log(MoreThanHalfNum_Solution1([2, 2, 2, 2, 2, 1, 3, 4, 5]),"MoreThanHalfNum_Solution1"); //2
闭包练习
12、闭包打印
/** * @description 参杂一个闭包看看 * @author cq * @Date 2021-01-11 18:05:16 * @LastEditTime 2021-01-11 20:01:45 * @LastEditors cq */ function fun(n, o) { console.log(o) return { fun: function (m) { return fun(m, n) } } } //注意看 最外层和最内层都有一个n // var a = fun(0);//undefined 此时n=0 闭包 // a.fun(1); //0 // a.fun(2); //0 // a.fun(3) //0 // undefined--0--1--2 // var b = fun(0).fun(1).fun(2).fun(3) // undefined--0 1 1 var c = fun(0).fun(1); c.fun(2); c.fun(3)