1、算法三大思维:贪心(二叉树找左)、二分、动态规划(大问题拆分成小问题,逐级向下分解,用递归思路分析,用循环来实现) 2、凡有序必二分,优化嵌套循环可以考虑双指针 // 把一个数组旋转k步 // 输入[1, 2, 3, 4, 5, 6, 7, 9], 3 // 输出[6, 7, 9,1, 2, 3, 4, 5 ] function rotating(arr, num) { return arr.slice(-num).concat(arr.slice(0, arr.length - num)) } function _rotating1(arr,num) { const spet = Math.abs(num % arr.length) for (let i = 0;i < spet;i++){ const n = arr.pop() if(n){ arr.unshift(n) } } return arr }
function _rotating2(arr,num) {
let arr2 = arr.slice(- num) for (let inx = arr.length - num - 1;inx >= 0;inx--) { arr[inx + num] = arr[inx] } for (let index = 0; index < num; index++) { arr[index]=arr2[index]
} return arr }
// 判断字符串是否括号匹配
function isMatch(left,right) {
if(left==='{'&&right==='}')return true
if(left==='['&&right===']')return true
if(left==='('&&right===')')return true
return false
}
function matchBracket(str) {
let stack = []
const leftSymbols = '({['
const rightSymbols = ')}]'
for (let i = 0; i < str.length ; i++) {
if(leftSymbols.includes(str[i])){
stack.push(str[i])
}else if(rightSymbols.includes(str[i])){
if(isMatch(stack[stack.length-1],str[i])){
stack.pop()
}else{
return false
}
}
}
return stack.length===0
}
console.log(matchBracket('{{()}}'));
// 数组转链表
let arr = [100, 200, 300, 400, 500, 600]
function anArrayOfLinkedList(arr) {
let length = arr.length
let curNode = {value:arr[length - 1]}
for (let inx = length - 2;inx >= 0;inx--) {
curNode = {
value: arr[inx],
next: curNode
}
} return curNode }
// 链表翻转 function listToFlip(obj) { let prevNode = undefined let cruNode = undefined let nextNode = obj while (nextNode) { if (!prevNode && cruNode) { delete cruNode.next } if (cruNode && prevNode) { cruNode.next = prevNode } prevNode = cruNode cruNode = nextNode nextNode = nextNode.next } cruNode.next = prevNode console.log( cruNode); return cruNode }
// 链表实现队列 class TheQueue { head = null tail = null len = 0 add(n) { const newNode = { value: n, next: null } if (this.head == null) { this.head = newNode } const tailNode = this.tail if (tailNode) { tailNode.next = newNode } this.tail = newNode } del() { const headNode = this.head this.head = headNode.next return headNode.value } } let theQueue = new TheQueue() // 二分查找 function binarySearch(arr, target) { let startIndex = 0 let endIndex = arr.length while (startIndex < endIndex) { console.log(startIndex , endIndex); const midindex = Math.floor((startIndex + endIndex)/2) const midvalue = arr[midindex] if(midvalue>target){ endIndex = midindex }else if(midvalue<target){ startIndex = midindex }else{ return midindex } } return -1 } // 找出数组中两个和为n的数 function findTowNumbers(arr, n) { let len = arr.length - 1 let start = 0, end = len while (start < end) { let num = arr[start] + arr[end] if (num > n) { end -= 1 } else if (num < n) { start += 1 } else { return [arr[start],arr[end]] } } } // 二叉树的遍历 // 前序遍历 function theFormerSequenceTraversal(obj) { if (obj === null) { return } console.log(obj.value); theFormerSequenceTraversal(obj.left) theFormerSequenceTraversal(obj.right) } // 中序遍历 function inTheSequenceTraversal(obj) { if (obj === null) { return } inTheSequenceTraversal(obj.left) console.log(obj.value); inTheSequenceTraversal(obj.right) } // 后序遍历 function afterTheSequenceTraversal(obj) { if (obj === null) { return } afterTheSequenceTraversal(obj.left) afterTheSequenceTraversal(obj.right) console.log(obj.value); } // 斐波那契数列// 0112358 function theFibonacciSequence(num) { if(num<2)return num return theFibonacciSequence(num-1)+theFibonacciSequence(num-2) } function theFibonacciSequence2(num) { let n1=1 let n2=0 let res=0 for (let inx = 1; inx < num; inx++) { res=n1+n2 n2=n1 n1=res
} return res } function fibonacci(num) { let sum = 0 let stack = [] for (let i = 0; i < num; i++) { if(i<2){ stack.push(i) }else{ let sum1=stack.pop() let sum2=stack.pop() sum = 1sum1+1sum2 stack.push(sum2,sum1,sum) }
} return stack } // 青蛙跳n级台阶有几种跳法 function theSteps(num) { if(num===1){ return 1 }else if(num===2){ return 2 }else{ return theSteps(num-1)+theSteps(num-2) } } //移动0到末尾 1020030110改为1231100000 // 1、0和非0分到两个数组再合并,2、如下双指针 function moveZero(arr) { let j = -1, len = arr.length for (let i = 0;i < len;i++) { if (arr[i] === 0) { if(j<0) j = i } else if (j >= 0) { const num = arr[i] arr[i] = 0 arr[j] = num j++ } } }
// 字符串中连续最多的字符 // 1、循环嵌套加跳步,2、双指针 function forTheMost(arr) { let len = arr.length, num = 0, char = '', bnum = 0, bchar = '' for (let inx = 0;inx < len - 1;inx++) { if (char === '') char = arr[inx], num = 1 // console.log(arr[inx] === char); if (arr[inx] === char) { num += 1 } else { if (bnum < num) { bnum = num, bchar = char } char = arr[inx]; num = 1 }
} return { bchar, bnum }
} function forTheMost2(str) { let obj = { value: '', num: 0 } for (let i = 0;i < str.length;i++) { let num = 0 const e = str[i]; for (let j = i;j < str.length;j++) { const e2 = str[j]; if (e === e2) { ++num } else { if (obj.num < num) { obj.value = str[i] obj.num = num } else { i = j-1 num = 0 } break }
}
} return obj } // 排序 function theSorting(arr) { let len = arr.length if (len === 0) return arr
let midindex = Math.floor(len / 2) let midvalue = arr.splice(midindex, 1)[0] let left = [] let right = [] for (let i = 0;i < arr.length;i++) { const n = arr[i] if (n < midvalue) { left.push(n) } else { right.push(n) } } return theSorting(left).concat([midvalue], theSorting(right)) }
// 获取对称数(回文数)1、如下翻转比较 2、数字收尾比较(栈)3、数字翻转(取余乘十,剩下的数再取余乘十,直到数小于0 )比较
/* / function numberOfSymmetry(num) { let arr = [] for (let i = 0;i < num;i++) { const s = i.toString() if (s === s.split("").reverse().join('')) { arr.push(i) } } return arr } function numberOfSymmetry2(num) { let arr = [] for (let i = 0;i < num;i++) { const s = i.toString() let flag = true, startIndex = 0, endIndex = s.length - 1 while (startIndex < endIndex) { if (s[startIndex] === s[endIndex]) { ++startIndex, --endIndex } else { flag = false break } } if (flag) { arr.push(i) } } return arr } function numberOfSymmetry3(num) { let arr = [] for (let i = 0;i < num;i++) { let num=i let total = 0 while (num > 0) { total =total10+ num % 10 num = Math.floor(num / 10) } if(total===i){ arr.push(i) } } return arr } // 千分位格式化 1234567转为 1,234,567
function micrometerLevel(num) { let str = '' while (num >= 1000) { let num2 = num % 1000 if (num2 < 100 && num2 >= 10) { str = ',0' + num2 + str } else if (num2 < 10) { str = ',00' + num2 + str } else { str = ',' + num2 + str } num = Math.floor(num / 1000) } return num + str }
function micrometerLevel2(num) { arr = Math.floor(num).toString().split('').reverse() return arr.reduce((prev, val, index) => { if (index % 3 === 0) { if (prev) { return val + ',' + prev } else { return val }
} else {
return val + prev
}
}, '') } function micrometerLevel3(num) { let res = '' let str = Math.floor(num).toString() for (let i = str.length - 1;i >= 0;i--) { if (i % 3 === 0) { res = str[i] + res if (i !== 0) { res = ',' +res } } else { res = str[i] + res } } return res }
// 切换字母大小写 65-90 97-122 大小写差32
function switchTheLetterCase(str) {
let res = ''
for (let i = 0;i < str.length;i++) {
const num= str.charCodeAt(i)
if(num>=65&&num<=90){
res+=String.fromCharCode(num+32)
}else if(num>=97&&num<=122){
res+=String.fromCharCode(num-32)
}else{
res +=str[i]
}
}
return res
}
// 扁平化
function recursive(arr) {
let res = []
for (let i = 0; i < arr.length; i++) {
if(Array.isArray(arr[i])){
let arrs=recursive(arr[i])
arrs.forEach(v => {
res.push(v)
});
}else{
res.push(arr[i])
}
}
return res
}
function flat(arr,arrr=[]) {
arr.forEach(item => {
if (Array.isArray(item)) {
return fn16(item,arrr)
} else {
arrr.push(item)
}
});
return arrr
}
// 数组转为树 function anArrayIntoATree(arr) { // 用于 id 和 treeNode 的映射 const idToTreeNode = new Map() let root = null arr.forEach(item => { const { id, name, parentId } = item // 定义 tree node 并加入 map const treeNode = { id, name } idToTreeNode.set(id, treeNode) // 找到 parentNode 并加入到它的 children const parentNode = idToTreeNode.get(parentId) if (parentNode) { if (parentNode.children == null) parentNode.children = [] parentNode.children.push(treeNode) } // 找到根节点 if (parentId === 0) root = treeNode }) return root }
//树转数组 广度优先遍历,用队列 如果深度优先遍历用栈 function treesTurnArray(obj) { let arr = [] let maps = new Map() let queue = [] queue.push(obj) while (queue.length > 0) { let curNode = queue.shift() let { id, name, children } = curNode const parentNode = maps.get(curNode) const parentId = parentNode && parentNode.id || 0 arr.push({ id, name, parentId: parentId || 0 }) if (children) { children.forEach(child => { maps.set(child, curNode) queue.push(child) })
}
}
return arr
}
// 等待+链式调用(把函数放到队列中,不是立即执行)
class LazyMan {
name = ''
tasks = [] // 任务列表
constructor(name) {
this.name = name
setTimeout(() => {
this.next()
})
}
next() {
const task = this.tasks.shift() // 取出当前 tasks 的第一个任务
if (task) task()
}
eat(food) {
const task = () => {
console.info(${this.name} eat ${food})
this.next() // 立刻执行下一个任务
}
this.tasks.push(task)
return this // 链式调用
}
sleep(seconds) {
const task = () => {
console.info(${this.name} 开始睡觉)
setTimeout(() => {
console.info(${this.name} 已经睡完了 ${seconds}s,开始执行下一个任务)
this.next() // xx 秒之后再执行下一个任务
}, seconds * 1000)
}
this.tasks.push(task)
return this // 链式调用
}
}
// 柯里化函数
function curry(fn) {
const fnArgsLength = fn.length // 传入函数的参数长度
let args = []
function calc(...newArgs) { // 积累参数 args = [ ...args, ...newArgs ] if (args.length < fnArgsLength) { // 参数不够,返回函数 return calc } else { // 参数够了,返回执行结果 return fn.apply(this, args.slice(0, fnArgsLength)) } }
return calc
}
function add(a, b, c) {
return a + b + c
}
// add(10, 20, 30) // 60
const curryAdd = curry(add)
const res = curryAdd(10)(20)(30) // 60