(小)算法题(长期更新)
class Queue{ container = [] enter(element){ this.container.push(element) } leave(){ return this.container.shift() } size(){ return this.container.length } value(){ return this.container } } function game(n, m){ let qe = new Queue // 把人放到队列 for(var i=0; i<n; i++){ qe.enter(i+1) } while(qe.size() > 1){ for(var j=0;j<m-1; j++){ qe.enter(qe.leave()) } qe.leave() } return qe.value().toString() } console.log(game(5, 3))
把十进制数字转换为二进制
class Stack{ container = [] enter(element){ this.container.unshift(element) } leave(){ this.container.shift() } size(){ this.container.length } value(){ return this.container } } Number.prototype.decimal2binary = function decimal2binary(){ let sk = new Stack let decimalNum = this.valueOf() if(decimalNum === 0) return '0' while(decimalNum > 0){ sk.enter(decimalNum % 2) decimalNum = Math.floor(decimalNum / 2) } return sk.value().join('') } var num=59 console.log(num.decimal2binary())
1.给定一个整数数组 nums
和一个目标值 target
,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
var twoSum = function(nums, target){ let res = new Map() for(var i=0,len=nums.length;i<len;i++){ if(res.has(target - nums[i])) return [res.get(target-nums[i]), i] res.set(nums[i], i) } console.log(res) } twoSum([2,5,7,8,9], 15) (2) [2, 3]
------------------------------------------------------------------------------------
// 类似给定数组,找出最大差值,最大的这个差值都是以右边 - 左边得出来的 如:var arr = [4,2,7,5,11,13,8,1] 当中最大差值是9 11-2 = 9
var arr = [4,2,7,5,11,13,8,1]
function maxDiff(arr){
if(arr.length<=1) return NaN
let min = Math.min(arr[0], arr[1])
let maxDiff = arr[1]-arr[0]
for(let i=0; i<arr.length; i++){
if(arr[i] > min) {
maxDiff = Math.max(maxDiff, arr[i]-min)
} else min = arr[i]
}
return maxDiff
}
console.log(maxDiff(arr))
[4,2,7,5,11,13,9,1].reduce((result, item, index, data) => Math.max(result, ...[...data].slice(0, index).map(v => item -v)));
[4,2,7,5,11,13,9,1].reduce((result, item, index, data) => Math.max(result, item - Math.min(...[...data].slice(0,index))));
// 给定一个整数无序数组和变量sum,如果存在数组中任意两项和使等于sum 的值,则返回true。否则 false
//例如数组 [3,5,1,4] 和sum=9
const findSum = (arr, sum) =>
arr.some((set => n => set.has(n) || !set.add(sum - n))(new Set));
var findSum = (arr, sum)=> arr.some((function(set){
return function (n){
return set.has(n) || !set.add(sum - n)
}
})(new Set))
第三大的数
var thirdMax = function(nums){ nums.sort((a, b)=> b-a) let map = new Map for(let i = 0,len=nums.length; i<len; i++){ let cur = nums[i] if(!map.get(cur)){ map.set(cur, 1) if(map.size === 3) return cur } } return nums[0] } console.log(thirdMax([2,3]))
2.递归案例:求一个数字,各个位数上的数字 和: 123 ---> 6
function getEverySum(x){ if(x<10) return x return x % 10 + getEverySum(parseInt(x/10)) } console.log(getEverySum(564564))
3. 数组 var arr = ['1-2', '2-8', '1-3', '2-4', '6-10', '2-5']
转换成:[ {key: 1, values: [2 , 3]}, {key: 2, values: [8, 4, 5]}, {key: 6, values: [10]}]
var arr = ['1-2', '2-8', '1-3', '2-4', '6-10', '2-5'] var fn = arr => { var res = [] var obj = arr.reduce((pre, cur)=> { var [k, v] = cur.split('-') pre[k] ? pre[k].push(v): pre[k] = [v] return pre }, {}) for(const [key, values] of Object.entries(obj)){ res.push({key, values}) }
// arr.map(v => v.split('-')).reduce((pre, [k, v])=> {
(pre[k] = pre[k] || []).push(v)
return pre
}, {})
// return Object.entries(obj).map(([key, values])=> ({key, values})) return res } console.log(fn(arr))
4.实现一个sum方法使其有以下表现
sum(2,3).valueOf() //5 sum(2,3,4).valueOf() //9 sum(2,3)(4).valueOf() //9 sum(2,3,4)(2)(3,4).valueOf() //18
// sum() 的结果可以继续使用 () 运算符,说明 sum() 返回的是一个函数(函数/函数表达式/箭头函数的统称);另外,这个返回值还有 valueOf() 方法,所以可以先搭个框 function sum() { const fn = () => {}; fn.valueOf = () => {}; return fn; } function sum(...args) { const r = args.reduce((a, b) => a + b); const fn = (...args) => { return sum(r, ...args); }; fn.valueOf = () => r; return fn; }
------------------------------------------------------------------------------
// 类似 fn(1).value = 1 fn(1)(2).value = 5 fn(1)(2)(3).value = 14
function fn(){
const a = function(m){
a.value = m*m
return a
}
a.value = 1
return a
}
5.递归修改json的key值
var dataObject = { "1": { "name": "第一级1", "type": "第一级2", "describe": "第一级3", "testNum": "第一级4", "1-1": { "name": "第二级5", "type": "第二级6", "describe": "第二级7", "testNum": "第二级8", "1-1-1": { "name": "第三级9", "type": "第三级q", "describe": "第三级w", "testNum": "第三级e" } } } }; // 将里面的1-1,1-1-1,1-2之类的值修改成对应的name字段里面的值,需要替换成下面这种的: var dataObject = { "第一级1": { "name": "第一级1", "type": "第一级2", "describe": "第一级3", "testNum": "第一级4", "第二级5": { "name": "第二级5", "type": "第二级6", "describe": "第二级7", "testNum": "第二级8", "第三级9": { "name": "第三级9", "type": "第三级q", "describe": "第三级w", "testNum": "第三级e" }, "第三级r": { "name": "第三级r", "type": "第三级ty", "describe": "第三级y", "testNum": "第三级y" } } } }
function generate(obj) { let _obj = {} Object.entries(obj).forEach(([key, value]) => { if (typeof value !== 'object') { _obj[key] = value } else { _obj[value.name] = generate(value) } }) return _obj } var res = generate(dataObject) console.log(res)
6. 输入一个值获取最近的值,并返回
var arr = [ ["IP-1", 0], ["IP-2", 13], ["IP-3", 68], ["IP-4", 138], ["IP-5", 149], ["IP-6", 834], ["IP-7", 1090], ["IP-8", 1247], ["IP-9", 1310], ["IP-10", 1956], ["IP-11", 2270], ["IP-12", 3337], ] // 出入 200,返回 IP-7
var res = function (value) { // 设置一个 map const map = new Map() // 设置每个 绝对值 和 name arr.forEach(x => { const number = Math.abs(value - x[1]) map.set(number, x[0]) }) // 得到 map里面最小的 value,得到名字 return map.get(Math.min.apply(null, Array.from(map.keys()))) } console.log(res(2000)) // IP-10
7. 2个多维数组查找交集 打标识
var A = [ {id: 1}, { id: 2, children: [ {id: 3}, {id: 4}, { id: 5, children: [{ id: 6 }] } ] } ]; var B = [ {id: 1}, { id: 2, children: [{ id: 5, children: [{ id: 6 }] }] }]; let c = method(A, B) //结果 c = [ {id: 1, disabled: true}, { id: 2, disabled: true, children: [ {id: 3}, {id: 4}, { id: 5, disabled: true, children: [{ id: 6, disabled: true }] } ] } ];
function method (treeA, treeB) { return dfs(treeA, new Set(flat(treeB))) } function dfs (root, dict) { for (node of root) { if (dict.has(node.id)) { node.disabled = true } if (node.children) { dfs(node.children, dict) } } return root } function flat (root, path = []) { for (node of root) { path.push(node.id) if (node.children) { flat(node.children, path) } } return path }
8.查找对象的上一级
var arr = [ { check: false, child: [ { check: false, child: [ { check: true, }, { check: true } ] }, { check: false, child: [ { check: true, }, { check: false, } ] } ] }, ] // 实现结果: var res= [ { check: false, child: [ { check: true, child: [ { check: true, }, { check: true } ] }, { check: false, child: [ { check: true, }, { check: false, } ] } ] }, ] --------------------------------------- function check (root) { const _checkNode = x => x.check = x.child ? x.child.every(_checkNode) : x.check root.forEach(_checkNode) return root }
var mapper = item =>
[item.child
&& (item.check = (item.child = item.child.map(mapper))
.filter(c => c.check).length === item.child.length)
, item][1]
console.dir(arr.map(mapper));
9
function Stack() { let items = [] // 存储数据 // 从栈顶添加元素,也叫压栈 this.push = function (item) { items.push(item) } // 弹出栈顶元素 this.pop = function () { return items.pop() } // 返回栈顶元素 this.top = function () { return items[items.length - 1] } // 判断是否为空 this.isEmpty = function () { return items.length == 0 } // 返回栈的大小 this.size = function () { return items.length } } /* * 思路: * 遇到左括号,就把左括号压入栈中 * 遇到右括号,判断栈是否为空,为空说明没有左括号与之对应,缺少左括号,字符串括号不合法 * 如果不为空,则把栈顶元素移除,这对括号抵消了 * * 当for循环结束后,如果栈是空,就说明所有的括号都抵消掉了 * 如果栈里还有元素,说明缺少右括号,字符串括号不合法 * * */ ------------------------------- // 判断字符串里的括号是否合法 function is_leagl_brackets(string) { let stack = new Stack() for (var i=0; i< string.length; i++) { var cur = string[i] if (cur == '(') { stack.push(cur) } else if(cur == ')') { if (stack.isEmpty()) { return false } else { stack.pop() } } } return stack.isEmpty() } console.log('111------', is_leagl_brackets('fasdfadsf()(fdsa()fsa(')) console.log('222------', is_leagl_brackets('fasdfadsf()')) -------------------------------------- // 逆波兰表达式,也叫后缀表达式,他将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式 // 例如(a+b)*(c+d) 转换为ab+cd+* //示例 ['4', '13', '5', '/', '+' ]等价于 (4 + (13/5)) = 6 // 4 入栈 // 13 入栈 // 5 入栈 // 遇到了 / 连续两次弹出栈顶元素 a b b / a = c c入栈 // 遇到 + 连续两次弹出栈顶元素 e f e + f = 6 6入栈 function calc_exp(exp) { let stack = new Stack() for (let i = 0; i <exp.length; i++) { let cur = exp[i] if (['+', '-', '*', '/'].includes(cur)){ let val1 = stack.pop(), val2 = stack.pop() let exp_str = val1 + cur + val2 // 计算并取整 var res = parseInt(eval(exp_str)) // 计算结果压入栈中 stack.push(res) } else stack.push(cur) } return stack.pop() } console.log('calc_exp(exp)------', calc_exp(['4', '13', '5', '/', '+' ]))
10.
var entry = { a: { b: { c: { dd: "abcdd" } }, d: { xx: "adxx" }, e: "ae" } }; // // 要求转换成如下对象 // var output = { // "a.b.c.dd": "abcdd", // "a.d.xx": "adxx", // "a.e": "ae" // } // 这道题是典型的DFS。这里有个技巧,就是将res作为参数传过去, // 从而子函数(helper)可以对其进行修改。 这样我们可以不必依赖返回值, // 也就避免了很多判断。 function helper(entry, prefix, res) { for (const key in entry) { if (entry[key] instanceof Object) { helper(entry[key], `${prefix}.${key}`, res); } else { res[`${prefix.slice(1)}.${key}`] = entry[key]; } } } function format(entry) { const res = {}; helper(entry, "", res); return res; } console.log(format(entry));
11.
list = [ { id: 1, label: 'a', children: [{ id: 4, label: 'b', children: [{ id: 9, label: 'c' }, { id: 10, label: 'd' }] }] } ] // 怎么根据label = c的条件 拿到 id为9的这条属性 varfind = (list, label) => { let result; for (let i = 0; i < list.length; i++) { const item = list[i]; if (item.label === label) { return result = item; } else { if (item.children) { result = find(item.children, label); } } } return result; }; var result = find(list, "c"); console.log(result);
12 求众数
给定一个大小为n的数组,找到其中的众数。众数是指在数组中出现次数大于 n / 2 的元素