一、算法
1、不重复字符的最长子串长度
题目:给定一个字符串,找出其中不含有重复字符的 最长子串 的长度。
var lengthOfLongestSubstring = function (s) {
const occ = new Set(), // 哈希集合,记录每个字符是否出现过
n = s.length
let rk = -1, ans = 0 // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
for (let i = 0; i < n; i++) {
if (i != 0) {
occ.delete(s.charAt(i - 1)) // 左指针向右移动一格,移除一个字符
}
while(rk + 1 < n && !occ.has(s.charAt(rk + 1))){
occ.add(s.charAt(rk + 1)) // 不断地移动右指针
++rk
}
ans = Math.max(ans, rk - i + 1) // 第 i 到 rk 个字符是一个极长的无重复字符子串
}
return ans
}
console.log(lengthOfLongestSubstring('abcdeab')); // 5
2、斐波那契数列
题目:斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给你 n ,请计算 F(n) 。
写法1:
var fib = function(n) {
if(n === 0) return 0;
if(n === 1) return 1;
let arr = [0,1];
for(let i = 0; i < n; i++){
let pre = arr[arr.length - 2],
last = arr[arr.length - 1]
arr.push(pre + last)
}
console.log(arr)
return arr[n]
};
写法2:
function fibomacci(n) {
if (n <= 1) return 1
let arr = [1, 1]
let i = n + 1 - 2 // 还要创建几位,n+1为位数 -2为去除数组固定的两个1后的位数
while (i > 0) {
let pre = arr[arr.length - 2],
last = arr[arr.length - 1]
arr.push(pre + last)
i--
}
return arr[arr.length - 1]
}
3、反转链表
题目:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
var reverseList = function(head) {
let prev = null,
curr = head
while(curr){
let next = curr.next;
curr.next = prev;
prev = curr;
curr = next
}
return prev
};
4、二叉树中和为某一值的路径
题目:输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
给定如下二叉树,以及目标和 target = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
返回
[
[5,4,11,2],
[5,8,4,5]
]
代码:
写法1:
var pathSum = function (root, sum) {
var res = [], stack = [];
function dfs(r, sum) {
if (r == null) return;
sum -= r.val;
stack.push(r.val);
if (r.left == null && r.right == null && sum == 0) res.push([...stack]);
dfs(r.left, sum);
dfs(r.right, sum);
stack.pop();
}
dfs(root, sum);
return res
};
写法2:
var pathSum = function(root, sum) {
if (root === null) return [];
const res = [];
const DFS = (root, sum, tmp) => {
if (root.val === sum && !root.left && !root.right) {
res.push(tmp);
}
tmp.push(root.val);
console.log(tmp.slice())
if (root.left) DFS(root.left, sum - root.val, tmp.slice()); // tmp.slice()浅拷贝
if (root.right) DFS(root.right, sum - root.val, tmp.slice());
}
DFS(root, sum, []);
return res;
};
二、手写题
手写Promise.all
Promise.all = function all(promises) {
var promiseNew,
results = [],
n = 0;
promiseNew = new Promise(function (resolve, reject) {
promises.forEach(function (promise, index) {
promise.then(function (result) {
n++;
results[index] = result
if (n >= promises.length) return resolve(results)
}).catch(function (e) {
return reject(e)
})
})
})
return promiseNew;
}
节流
function throttle(func, wait) {
var timer = null,
previours = 0, //上次触发时间
result;
return function proxy() {
var now = +new Data(),
remaining = wait - (now - previours), // 还差多久
self = this,
props = [].slice.call(arguments)
if (remaining <= 0) {
if (timer) {
clearTimeout(timer)
timer = null
}
result = func.apply(self, props)
previours = +new Data()
} else if (!timer) {
timer = setTimeout(function () {
if (timer) {
clearTimeout(timer)
timer = null
}
result = func.apply(self, props)
previours = +new Data()
}, remaining)
}
return result
}
}
function fn() {
console.log('ok');
}
throttle(fn, 500)
防抖
function debounce(fn, wait) {
let timer = null,
result
return function () {
let self = this,
props = [].slice.call(arguments)
if (timer) clearTimeout(timer)
timer = setTimeout(function () {
result = fn.apply(self, props)
}, wait)
return result
}
}
冒泡排序
var arr = [3, 4, 1, 2]
function maopao(arr) {
var max = arr.length - 1
for (var i = 0; i < max; i++) {
for (var j = 0; j < max - i; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
console.log(arr);
return arr
}
maopao(arr)
快排
function quickSort(arr) {
if(arr.length<1) return arr;
var poivtIndex = Math.floor(arr.length/2)
var poivt = arr.splice(poivtIndex, 1)[0]
var left = []
var right = []
for(var i=0; i<arr.length; i++) {
if(arr[i]<poivt) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
return quickSort(left).concat([poivt], quickSort(right))
}
var arr = [2,3,4,6,1,5]
console.log(quickSort(arr)) // [1,2,3,4,5,6]
数字的千分位分隔
12345 --> 12,345
function fenge(str) {
str = str + ''
let arr = str.split('')
for (let i = arr.length - 3; i > 0; i = i - 3) {
arr.splice(i, 0, ',')
}
arr = arr.join('')
console.log(arr)
}
fenge(1234567812345678)
格式化展示文件大小
// 方法一
function fileSize(size, toFixed) {
let arr = ["Bytes", "KB", "MB", "GB", "TB"]
let index = 0,
srcsize = parseFloat(size)
index = Math.floor(Math.log(srcsize) / Math.log(1024))
let sizes = srcsize / Math.pow(1024, index)
sizes = sizes.toFixed(2)
console.log(sizes + arr[index])
return sizes + arr[index]
}
fileSize(1023);// 1023b
fileSize(1024); // 1kb
fileSize(2000); // 1.953125kb
fileSize(2000, 2); // 1.95kb
fileSize(2 * 1024 * 1024); // 2mb
fileSize(1234 * 1024 * 1024 * 1024); // 1234tb
function fileSize(B, toFixed) {
let arr = ['B', "KB", "MB", "GB", "TB"]
let val = B / 1024
let i = 0
if (val < 1) {
i = 0
val = B + arr[i]
} else if (val >= 1 && val < 2) {
i = 1
val = val + arr[i]
} else {
let temp = 1
while (val >= 1024) {
val = val / 1024
temp++
}
val = val + arr[temp]
console.log(val);
}
}
fileSize(2456 * 1024 * 1024);
二分查找
非递归
const search = function (arr, value) {
let start = 0,
end = arr.length - 1
while (start <= end) {
let mid = Math.floor((start + end) / 2)
if (arr[mid] == value) {
return mid
} else if (arr[mid] > value) {
end = mid - 1
} else {
start = mid + 1
}
}
return -1
}
递归
const search = (arr, value, start, end) => {
if (start > end) {
return -1
}
let mid = Math.floor((start + end) / 2)
if (arr[mid] == value) {
return mid
} else if (arr[mid] > value) {
end = mid - 1
search(arr, value, start, end)
} else {
start = mid + 1
search(arr, value, start, end)
}
}
深克隆
function deepClone(obj){
//过滤特殊情况
if(obj === null) return null;
if(typeof obj !== "Object") return obj;
if(obj instanceof RegExp){
return new RegExp(obj)
}
let newObj = obj instanceof Array?[]:{}
for (let i in obj){
if(obj.hasOwnProperty(i)){
newObj[i] = deepClone(obj[i])
}
}
return newObj;
}
let obj2 = deepClone(obj)
驼峰转短线分隔形式
function change(str){
str = str.split('')
let newStr=''
for(let i=0;i<str.length;i++){
if((str[i].charCodeAt(0) < 90) && (str[i].charCodeAt(0) > 65)){
let s = str[i].toLowerCase()
newStr = newStr + '-' + s
}else{
newStr= newStr + str[i]
}
}
return newStr
}
let a = change('getElementById')
console.log(a) //get-element-by-id
async,await,promise 实现定时器效果,每隔一秒输出数组中的数字
let arr = [1, 1, 1, 1]
function sleep() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 1000)
})
}
(async () => {
for (let i of arr) {
await sleep()
console.log(i);
}
})()