无重复字符的最长子串
篮子算法
链表
栈
// 题目描述: 输入字符串,()匹配,如果是有效的输出所有括号里的内容,否则输出error
//输入 ((2+3) + (4+5)) + 8, 输出[(2 + 3), (4 + 5), ((2+3) + (4+5))]
//输入((2+3) + (4+5) + 8, 输出error
// 采用栈的方式,(符号下标入栈,) 符号栈元素出来,如果碰到“)”,此时栈为空,那肯定不是有效字符串,如果遍历结束栈里元素没出完,也不是有效的,其它的时候,根据出栈的值和当前“)”的位置获取字符串
function fn(str) {
const res = [];
const arr = [];
for (let i =0 ; i < str.length; i++) {
if (str[i] === '(') {
arr.push(i);
continue
}
if (str[i] === ')') {
if (!arr.length) return 'error';
const idx = arr.pop();
res.push(str.substring(idx, i+1))
}
}
if (arr.length) return 'error';
return res;
}
排序算法
快排
function quickSort(arr, left, right) {
var len = arr.length,
partitionIndex,
left = typeof left != 'number' ? 0 : left,
right = typeof right != 'number' ? len - 1 : right;
if (left < right) {
// 第一步 找分割点
partitionIndex = partition(arr, left, right);
// 第二步 分别递归分割点左右2侧的数据
quickSort(arr, left, partitionIndex-1);
quickSort(arr, partitionIndex+1, right);
}
return arr;
}
function partition(arr, left ,right) { // 分区操作
var pivot = left, // 设定基准值(pivot)
index = pivot + 1;
// 分割点的原理,主要是index记录所有比pivot小的(大的)有多少个
for (var i = index; i <= right; i++) {
if (arr[i] < arr[pivot]) {
swap(arr, i, index);
index++;
}
}
swap(arr, pivot, index - 1);
return index-1;
}
function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
堆排序(www.runoob.com/w3cnote/hea…)
let len;
const heapSort = (nums) => {
// 首先建立大顶堆(小顶堆),此时第一个数就是最大值(最小值)
buildMaxHeap(nums);
/**
其次进行堆排序,
主要是将最大值(第一位)和最后一个位置进行交换,
然后剔除最大值后剩余的进行堆调整
*/
for (let i = nums.length; i--; i > 0) {
swap(nums, 0, i);
len--;
heapify(nums, 0)
}
console.log(nums, '--nums')
return nums
}
// 建立大顶堆
const buildMaxHeap = (nums) => {
len = nums.length;
// 从中间节点开始
for (let i = Math.floor(len/2); i >= 0; i--) {
heapify(nums, i)
}
}
// 堆调整
const heapify = (nums, i) => {
let largest = i, // 用来标记最大元素
left = 2 * i + 1, // 左节点
right = 2 * i + 2;// 右节点
if (left < len && nums[left] > nums[largest]) {
largest = left
}
if (right < len && nums[right] > nums[largest]) {
largest = right
}
if (largest !== i) {
swap(nums, i, largest);
heapify(nums, largest)
}
}
// 元素交换
const swap = (nums, i, j) => {
const temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
一年中的第几天
var dayOfYear = function(date) {
var months = [31,28,31,30,31,30,31,31,30,31,30,31]
var year = +date.slice(0, 4);
var month = +date.slice(5, 7);
var day = +date.slice(8);
var res = 0;
if (year % 400 === 0 || (year % 4 === 0 && year % 100 !==0)) {
++months[1];
}
for (var i = 0; i < month - 1; i++) {
res+= months[i];
}
return res + day
};
三数之和
数组/left、right指针
两个数的乘积
LRU
防抖与节流
function debounce(fn, time) {
let timeId;
let _this = this
function debounced() {
if (timeId) {
clearSetTimeout(timeId)
}
timeId = setTimeout(fn.apply(this,arguments) ,time)
}
return debounced
}
function throttle(fn, time) {
let currentTime = 0;
function throttled() {
let now = new Date().getTime();
if (now- currentTime > time) {
currentTime = now;
setTimeout(fn.apply(this, arguments), 0)
}
}
return throttled
}
深度遍历和广度遍历
深度遍历(递归)
function deepTransfer(node, nodelist) {
if (!node) return []
nodelist.push(node)
for (let i = 0; i < node.children.length; i++){
deepTransfer(node.children[i], nodelist)
}
return nodelist
}
深度遍历(栈)
function deepTransfer(node) {
// nodelist 用来保存结果, stack用来实现遍历顺序
let stack = [], nodelist = [];
if (!node) return [];
stack.push(node)
while(stack.length) {
let currentNode = stack.pop();
nodelist.push(currentNode)
for (let i = currentNode.children.length - 1; i >= 0; i--) {
stack.push(currentNode.children[i])
}
}
return nodelist
}
广度遍历(队列)
function widthTransfer(node) {
let stack = [], nodelist = [];
if (!node) return [];
stack.push(node);
while(stack.length) {
let currentNode = stack.shift();
nodelist.push(currentNode)
for(let i = 0; i < currentNode.children.length; i++) {
stack.push(currentNode.children[i])
}
}
return nodelist
}
async/await
/**
function *func() {}
let gen = func();
gen.next()
*/
function asyncToGenerator(generatorFunc) {
return function() {
let gen = generatorFunc.apply(this, arguments);
return new Promise((resolve, reject) => {
function step(key, arg){
let generatorResult;
try{
generatorResult = gen[key](arg)
} catch(err) {reject(err)}
let {value, done } = generatorResult;
if (done) {
return resolve(value)
} else {
return Promise.resolve(value).then((val) => {step('next', val), (err) => step('throw', err)})
}
}
step('next')
})
}
}
数组扁平化
function func(arr) {
let res = []
if (!arr.length) return []
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
res = res.concat(func(arr[i]))
} else {
res.push(arr[i])
}
}
return res
}
Promise
/**
使用var a = new Promise((resolve, reject) => {}).then(resolve, reject)
状态:pending/fulfilled/rejected
*/
function noop(){}
function resolvePromise(promise, value, resolve, reject) {
if ((typeof value === 'object' && value !== null ) || typeof value === 'function') {
if (typeof value.then === 'function') {
// 如果value是函数的话,执行then继续,
value.then.call(value, (success) => {
resolvePromise(promise, success, resolve, reject)
}, (fail) => {
reject(fail)
})
} else {
resolve(value)
}
} else {
resolve(value)
}
}
function Promise(fn) {
const self = this;
// promise状态
self.state = 'pending';
// 成功的值
self.value = undefined;
// 异常的原因
self.reason = undefined;
// 存放成功的回调
this.onResolvedCallbacks = [];
// 存放失败的回调
this.onRejectedCallbacks= [];
function resolve(value) {
self.state = 'fulfilled';
self.value = value;
// 依次将对应的函数执行
self.onResolvedCallbacks.forEach(fn=>fn());
}
function reject(reason) {
self.state = 'rejected';
self.reason= reason;
// 依次将对应的函数执行
self.onRejectedCallbacks.forEach(fn=>fn());
}
try {
fn(resolve, reject)
} catch (error) {
reject(error)
}
}
Promise.prototype.then = function(resolve, reject) {
const self = this;
// 这里的resolve/ reject可能没值,需要包装下
resolve = typeof resolve === 'function' ? resolve : noop;
reject = typeof reject === 'function' ? reject : function(err){throw(err)}
let promise2 = new Promise((_resolve, _reject) => {
if (self.state === 'fulfilled') {
// 这里的res可能是then执行后返回的Promise,因此需要循环继续调用
setTimeout(() => {
try {
let res = resolve(self.value);
resolvePromise(promise2, res, _resolve, _reject)
} catch (error) {
reject(error)
}
}, 0)
}
if (self.state === 'rejected') {
setTimeout(() => {
try {
let res = reject(self.reason);
resolvePromise(promise2, res, _resolve, _reject)
} catch (error) {
reject(error)
}
}, 0)
}
if (self.state === 'pending') {
self.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let res = resolve(self.value);
resolvePromise(promise2, res, _resolve, _reject)
} catch (error) {
reject(error)
}
}, 0)
})
self.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let res = reject(self.reason);
resolvePromise(promise2, res, _resolve, _reject)
} catch (error) {
reject(error)
}
}, 0)
})
}
});
return promise2;
}
ajax
function ajax(method = 'get', url) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (!this.readyState !== 4) return;
if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) { // success } else { // error }
}
xhr.open(method,url, 'async');
xhr.send();
}
异步scheduler
class scheduler {
constructor(limit) {
this.list = [];
this.limit= limit;
this.idx = 0;
}
add(cb) {
this.list.push(cb)
this.run();
}
async run() {
this.limit -= 1;
while(this.idx < this.list.length && this.limit) {
const shift = this.list.shift();
this.idx += 1;
await shift()
this.limit += 1
}
}
}
并发控制
// 主要通过limit的加减控制的,如果有程序运行limit-1, 程序执行结束limit+1, 如果limit为0的时候不执行
function sendRequest(requests, limit) {
return new Promise((resolve, reject) => {
const len = requests.length;
let idx = 0;
let count = 0;
const send = async () => {
while(idx < len && limit) {
limit--;
const request = requests[idx++];
request().then((a) => {
limit++;
count++;
console.log(a, '---aaa')
if (len === count) {
resolve()
} else {
send();
}
})
}
}
send();
})
}
const list = new Array(50).fill(0).map((a, idx) => {
return function() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(idx);
}, 1000);
});
}
});
sendRequest(list, 4)
将数组扁平化为树结构
const data1 = [
{
id: 1,
pid: 0,
name: "body",
},
{
id: 2,
pid: 1,
name: "title",
},
{
id: 3,
pid: 2,
name: "div",
},
{
id: 4,
pid: 0,
name: "div",
},
{
id: 9,
pid: 4,
name: "div",
},
];
//通过map引入的方式
const transformArrayToTree = (arr) => {
let res = [] // 结果存储
let mapObj = {} // 通过对象临时记录
// 首先给每一个添加children
for (const item of arr) {
mapObj[item.id] = {
...item,
children: []
}
}
// 通过对象引入关联,pid=0的存储到res数组中,其它的是在父节点pid的children下,通过push当前id的节点
for (const item of arr) {
// 这里的push采用mapObj保存的临时的,不要采用item原有的
if (item.pid === 0) {
res.push(mapObj[item.id]);
continue;
}
mapObj[item.pid].children.push(mapObj[item.id])
}
return res
}
// 通过递归的方式
const transformArrayToTree = (arr) => {
let res = [];
const getChildren = (_res, parentId) => {
for (const item of arr) {
if (item.pid === parentId) {
const newItem = {...item, children: []}
_res.push(newItem);
getChildren(newItem.children, newItem.id)
}
}
}
getChildren(res, 0)
return res;
}