js算法(个人整理_彦超)
LRU算法
1、利用 Map 既能保存键值对,并且能够记住键的原始插入顺序
2、获取数据 get(key) - 如果密钥 ( key ) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1 。
3、写入数据 put(key, value) - 如果密钥不存在,则写入数据。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据,从而为新数据留出空间。
class Lru_cache {
constructor(max) {
this.max = max;
this.cache = new Map();
}
get(key) {
let value = this.cache.get(key);
if (!value) return;
this.cache.delete(key);
this.cache.set(key, value);
return value;
}
add(key, value) {
if (this.cache.size > this.max - 1) {
const keys = this.cache.keys().next().value;
this.cache.delete(keys);
}
this.cache.set(key, value);
}
}
const lru = new Lru_cache(4);
lru.add(1, 1);
lru.add(2, 2);
lru.add(3, 3);
lru.add(4, 4);
lru.get(2);
lru.get(2);
lru.get(2);
lru.add(5, 5);
console.log(lru.cache);
原始 list 转换成树形结构
let list =[
{id:1,name:'部门A',parentId:0},
{id:2,name:'部门B',parentId:0},
{id:3,name:'部门C',parentId:1},
{id:4,name:'部门D',parentId:1},
{id:5,name:'部门E',parentId:2},
{id:6,name:'部门F',parentId:3},
{id:7,name:'部门G',parentId:2},
{id:8,name:'部门H',parentId:4}
];
let convert = arr => {
let convert_ = list.reduce((res, v) => (res[v.id] = v, res), {})
return arr.reduce((arr_, i) => {
let parent = convert_[i.parentId]
if (parent) {
parent.child ? parent.child.push(i) : parent.child = [i]
} else if (i.parentId== 0) {
arr_.push(i)
}
return arr_
}, [])
}
数组去重
(空间复杂度最低)
function uni(arr) {
let l = arr.length;
arr.sort((a, b) => a - b)
for (let i = 0; i < l; i++) {
if (arr[i] == arr[i + 1]) {
arr.splice(i, 1);
l--;
i--;
}
}
return arr;
}
斐波那契数
function Fir(s){
if(s<2){
return s
}else{
return Fir(s-1)+Fir(s-2)
}
}//递归算法
function Fir(s){
let _=Array.from({length:s},i=>i=0)
_[1]=1
_[2]=2
if (s<3)return 1;
for(let i=3;i<s;i++){
_[i]=_[i-1]+_[i-2]
}
return _[s-1]
}//动态规划算法
实现二分搜索法
function getIndex(arr, num) {
arr.sort(a,b=>a-b)
var start = 0,
end = arr.length - 1
while (start <= end) {
var mid = Math.floor((start + end) / 2)
if (num == arr[mid]) {
return mid
}
if (num > arr[mid]) {
start = mid + 1
}
if (num < arr[mid]) {
end = mid - 1
}
}
return false
}
2数之和
function twoSum(arr, k) {
let arr_=arr.sort((a,b)=>{a-b})
let L=0,R=arr_.length-1,_=[]
while(L<R){
let val=arr[L]+arr[R]
if(val>k) R--
if(val<k) L++
if(val==k) _.push([arr[L],arr[R]])
}
return _
}//二分法
function twoSum(arr, k) {
let newArr = []
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] + arr[j] == k) {
newArr.push(arr[i], arr[j])
}
}
}
return newArr
}//暴力法
function twoSum(arr, k) {
let _ = {}
for (let i = 0; i < arr.length; i++) {
let val=k-arr[i]
if(val in _){
return [_[val],i]
}
_[arr[i]]=i
}
}//循环过程中将数值的值和下标存储在对象里面
最长公共前缀
var longestCommonPrefix = function(arrString) {
if (arrString === null || arrString.length === 0) return "";
if (arrString.length === 1) return arrString[0]
let min = 0,
max = 0
//求数组最长(大)值和数组最短(小)值
for (let i = 0; i < arrString.length; i++) {
if(arrString[max]<arrString[i]) max=i
if(arrString[min]>arrString[i]) min=i
}
//对数组最短值进行循环
for (let i = 0; i < arrString[min].length; i++) {
if (arrString[min][i] !== arrString[max][i]) {
return arrString[min].slice(0, i)
}
}
return arrString[min]
}//获取数组中的最大值及最小值字符串,最小字符串与最大字符串的最长公共前缀也为其他字符串的公共前缀,即为字符串数组的最长公共前缀
无重复字符的最长子串
var lengthOfLongestSubstring = function(s) {
var res = 0; // 用于存放当前最长无重复子串的长度
var str = ""; // 用于存放无重复子串
for (var i = 0; i < s.length; i++) {
if (str.indexOf(s[i]) !== -1) { //有重复的情况
str = str.slice(str.indexOf(s[i]) + 1) + s[i];
//截取重复元素之后的元素,并且和下一个元素进行拼接,实现动态截取
//类似于url.slice(url.indexOf('?')+1)意味截取url中的参数
} else { //无重复的情况
str += s[i];
res = str.length > res ? str.length : res;
//每次循环截取会产生不同长度的 str,此处只取最长的 str
}
}
return res;
};
山脉数组
var validMountainArray = function(A) {
if (A.length < 3) return false
let i = 0;
let j = A.length - 1;
//左指针从左向右移动,最大移动不能大于右指针,则范围为< A.length - 2
//且符合山脉数组则每后一项大于前一项
while (i < A.length - 2 && A[i] < A[i + 1]) {
i++
}
//右指针从右向左移动,最大移动不能大于左指针,则范围为< A.length - 2
//且符合山脉数组则每后一项小于前一项
while (j > 1 && A[j] > A[j + 1]) {
j--
}
//有且只有一个顶点
return i === j
};