js算法进阶

function splitMoney(num){
       const arr = num.toString().split('.');
       const numarr = arr[0].split('');
       const reverseNum = numarr.reverse();
       for(let i =3,len = reverseNum.length ;i<len;i+=3){
            reverseNum.splice(i,0,',');
            i++;
        }
        const result = revereNum.join('').reverse()+arr[1];
        console.log(result);
}

1,{[()]}

一个字符串,该字符串只可能包含:‘[,],{,},(,)',其中的几个,判断该字符串是否符合以下规则:

左括号必须使用相同类型右括号闭合
必须以正确顺序闭合

例如:输入 {() } :true
输入([)]:false
输入([): false

function judge(str){
 //思路,将字符串中所有括号的左边push到数组,然后遇到括号右边的就和数组最后一个对比,如果符合就从数组里pop出去。

const arr=[];
const len = str.length;
if(len%2!==0)return false;

for(let i = 0;i<len;i++){
const end = arr.length;
  switch(s[i]){
    case '(':
        arr.push('(');
        break;
    case '[':
        arr.push('[');
        break;
    case '{':
        arr.push('{');
        break;
    case ')':
        if(arr[end-1] === '(')arr.pop();
        break;
    case ']':
        if(arr[end-1] === '[')arr.pop();
        break;
    case '}':
        if(arr[end-1] === '{')arr.pop();
        break;
    } 
 }
if(arr.length>0)return false
else{ return true }
}

2,字符串反转

使用数组的reverse方法,实现字符串反转?(也可以用来判断回文字符:mamam,redivider)

function reverseStr(str){

return str.split('').reverse().join('');

}

2.1 字符串反转(不用reverse)

function reverseStr(str){
  const len = str.length;
  for(let i=0,j=len-1;i<j;i++,j--){
    [str[i],str[j]] = [str[j],str[i]] 
  }
  return str;
}

3,判断一个单链表是否存在闭环?

思想:快指针,慢指针

function ListNode(list){
    this.value = val;
    this.next = null
}

function hasCycle(head){
    var slow = head;
    var fast = head;
    while(slow.next != null || fast.next != null){
         slow = slow.next;
         fast = fast.next.next;
         if(slow === fast){
                return true
            }
    return false
   }
}

4,sum(1,2,3) = sum(1)(2)(3)

实现一个sum函数,使得sum(1,2)==sum(1)(2)

首先实现sum(1,2)

function sum(){
    if(arguments.length>0){
    arguments.map(item=>{
         result+=item
      }
    };
   return  result
}

然后实现sum(1)(2)

function sum(a){
    return function(b){
        return a+b
}
}

 实现sum(1)(2)(3)

function sum(a){
 const s = function(b){
   return sum(a+b)
 }
 s.toString = function(){ return a };
 return s
}

二者结合

function sum(a){
const len = arguments.length;
    var value = 0;
        if(len>1){
            for(var i=0;i<arguments.length;i++){
                value+=arguments[i];
            }
          return value;
        }
        else {
        var s = function(b){
            return sum(a+b);
        }
        s.toString = function(){
            return a;
        }
        return s;
    }
}

4.1附加题  实现sum(1)(2)(3)() 

function add(num,preSum){
   var result = preSum || 0;
    return num?function(nextNum){
            result += num;
            return add(nextNum,result)
        }:result;
}

5,分离单调递增数组连续区间

给定一个单调递增的数组,比如[1,2,3,5,6,7,11,12],输出连续区间,得[1,2,3], [5,6,7], [11,12]

function source(arr){
  let i;
  let a ;
  let result = [];
  arr.forEach(function(v){
  if(v == i){
   a.push(v);
   i++;
   return
  }
  let a = [v];
  i = v+1;
  result.push(a);
})
return result
}

6,数组去重

不使用Set,将数组去重?

function set(arr){
 var result = [];
 var obj = {};
  arr.map(item=>{
   if(!obj[item]){
     obj[item] = true;
     result.push(item)
   }
}
return result;
}

7,统计字符串中出现次数最多的字母?

function maxstr(str){
    var obj = {};
    const arr = str.split('');
    var max = 0;
    arr.map(item=>{
      if(obj[item]){
        obj[item]++
      }else{
        obj[item] = 1;
      }
    })
    
    var sub;
    for(let key in obj){
      if(obj[key]>max){
        max = obj[key];
        sub = key;
      }
    }
      return sub
    }
    
maxstr("aaabbbbcccc")

8,冒泡排序? 

 [3,5,6,1,7,2]  排为 [1,2,3,5,6,7] 

function sort(arr){
  let len = arr.length;
  for(let i = 0;i<len;i++){
     for(let j = i;j<len;j++){
         if(arr[i]>arr[j]){
            const item = arr[i];
            arr[i] = arr[j];
            arr[j] = item;
         }
      }
  }
  console.log(arr);
}

9,判断一个数是否为素数(质数)?

素数的意思是这个数除了1和自己,没有其他的因子了。比如2,3,5,7,11,13,17,19,23,29,31,37........

分析这些数字之间相差(2,4,6),所以只要不仅除不尽2,也除不尽3,以及(3+2,3+4,3+6....)的数字,它就是素数,然后它的被除数最大应该是它的平方根

function isPrime(num){
    if(num===2||num===3)return true;
    if(num%2===0)return false;
    const sqrt = Math.sqrt(num);
    var divider = 3;
    while(divider<sqrt){
    if(num%divider === 0){
        return false
     }else{
        divider+=2
    }
    }
    return true
  }
}

10,斐波那契数列

function febonacci(num){
    if(num===0)return 0;
    if(num ==1||num==2)return 1;
    else{
    return febonacci(num-2)+febonacci(num-1)
    }
}

11,快速排序

function quicksort(arr){
    const len = arr.length;
    if(len<2)return arr;
    const mid = Math.floor(len/2);
    const left = [];
    const right = [];
    var pivot = arr.splice(mid, 1)[0];

    arr.map(item=>{
    if(item<pivot){
      left.push(item)
    }else{
      right.push(item)
    }
   })
  const leftResult =  quicksort(left);
  const righResult =  quicksort(right);
  return  leftResult.concat([pivot],righResult)
}

12,合并已经排过序的两个数组?

function merge(a,b){
    var i = 0;
    var j = 0;
    var af = a[0];
    var bf = b[0];
    var result = [];
    while(af||bf){
      if(af<bf||!bf){
        result.push(af);
        af = a[++i];
      }else{
        result.push(bf);
        bf = b[++j];
      }
    }
    return result;
}

13,实现深拷贝deepclone

function deepclone(obj){
   if(typeof obj === "object"){
     var result = Array.isArray(obj)?[]:{};
     for(let item in obj){
        result[item] = deepclone(obj[item]);
     }
    }else{
       return obj
    }
}

14,数组转化为树?

这题有点问题啊~,pid:0,但是没有id:0的节点

将[
        {id: 1, pid: 0 , name:"上海"},
        {id: 2, pid: 1 , name:"苏州"},
        {id: 3, pid: 1 , name:"安徽"},
        {id: 4, pid: 0 , name:"杭州"}
]
转化为:
  [
     {  id: 1,
        pid: 0,
        name: "上海",
        children:[
            {id: 2, pid:1,  name:"苏州"},
            {id: 3, pid:1,  name:"安徽"}
           ],
     },
     {    id:4,
          pid: 0,
          name:"杭州",
     }
 ]

思路:先转化成这样

 {
  0: [ {id: 1, pid: 0 , name:"上海"},{id: 4, pid: 0 , name:"杭州"}],
  1: [{id: 2, pid: 1 , name:"苏州"},{id: 3, pid: 1 , name:"安徽"}]
}

再把原来的arr里插入chidren

  [
     {  id: 1,
        pid: 0,
        name: "上海",
        children: [{id: 2, pid: 1 , name:"苏州"},{id: 3, pid: 1 , name:"安徽"}]    //map.get(1)
     },
    {id: 2, pid: 1 , name:"苏州"},
    {id: 3, pid: 1 , name:"安徽"},
    {id: 4, pid: 0 , name:"杭州"}
 ]

function arrToTree(arr){
    let map = new Map();
    arr.forEach(item => {
        if(!map.has(item.pid)){
            map.set(item.pid, [item])
        }else {
            let arr1 = map.get(item.pid);
            arr1.push(item)
        }
    })

   arr.forEach(item => {
        if(map.has(item.id)){
           item.children = map.get(item.id);
        }
   })

    return map.get(0);
}

15,大数相加

两个很大的数字相加,超出计算机允许的长度,可以用字符串表示,例如:
bigNum("111111111","999999999999") 返回的结果也是字符串

function bigNum(num1,num2){
   while(num1.length<num2.length){num1 = '0'+num1;}
   while(num1.length>num2.length){num2 = '0'+num2;}
   let len = num1.length;
   let result = '';
   let carray = 0;
   let mid = 0;
   for(let i = len-1;i>=0;i--){
     mid = Number(num1[i])+Number(num2[i])+carray;
     carray = mid>9?1:0;
     let wei = mid%10;
     result = wei+result;
   }
   return  carray?('1'+result):result
}

16,数组扁平化

//通用的
function flat(arr){
 let result = [];
 arr.map(item=>{
    if(!Array.isArray(item)){
    result.push(item)
    }else{
     const pin = flat(item);
     result = result.concat(pin);
    }
  })
return result;
}

//元素类型是字符串['1','2','3'],可以这样
function flatArray(arr){
  return arr.toString().split(',');
}

17,千位分隔符

将123345.56元,分割为123,345.56

function splitMoney(num){
       const arr = num.toString().split('.');
       const reverseNum = arr[0].split('').reverse();
       let res = [];
       let len = reverseNum.length;
       for(let i =0;i<len;i++){
         if(i%3===0&&i!==0){
            res.push(',');
         }    
            res.push(reverseNum[i]);
        }
        if(arr[1]){
            arr[1]='.'+arr[1];
        }
        const result = res.reverse().join('')+arr[1];
        console.log(result);
}

18,找到数组中所有重复的元素的个数?

比如:[1,11,1,2,3,3,4,5],重复的元素有两个:1和3,所以返回2;

function ag(arr){
   const obj = {};
  arr.map(item=>{
      obj[item] = obj[item]|| 0;
      obj[item]++
  })
var len = 0;
  for(let it in obj){
      if(obj[it]>1){
       len++
      }
  }
 console.log(len)
}

19,找到数组中和为n的两个数的下标?

例如[1,3,5,6] ,target = 8,则返回下标:1,2

function twoSum(arr,target){
    const len = arr.length;
    var hashMap = {};
    for(let i = 0;i<len;i++){
       if(hashMap[target-arr[i]]!==undefined){
            console.log(hashMap[target-arr[i]],i)
        }
       hashMap[arr[i]]=i
    }
}

20,区间合并

比如:  [[1,3],[2,6],[8,10],[15,18]]     合并为 [[1,6],[8,10],[15,18]]
因为区间 [1,3] 和 [2,6] 重叠, 所以将它们合并为 [1,6]

function mergeArr(arr){
  arr =  arr.sort((a,b)=>{
        a[0]-b[0]
    });
  let result = [arr[0]];
  let j = result.length-1;
  let mid;
   for(let i = 0;i<arr.length;i++,j = result.length-1){
        if(result[j][1]>arr[i][0]){
            if(result[j][1]>arr[i][1]){
                mid = [result[j][0],result[j][1]]
            }else{         
                mid = [result[j][0],arr[i][1]]
            }
            result.pop();
            result.push(mid)
        }else{
            result.push(arr[i]);
        }
   }
  return result;
}

21,手写bind函数

22,手写call函数

核心思想:谁调用函数,函数的this就指向谁。

本来是window.fn(),现在修改为obj.fn(),那么fn的this就指向obj了。

不过call函数内部无法预知哪个函数将要调用自己,所以obj.fn = this,obj.fn()

Function.prototype.calls=function(obj){
     obj.fn = this;
     const arg= [...arguments].slice(1);
     obj.fn(arg)
     delete obj.fn
}

23,求最后一个单词的长度

比如:“hello world",返回 5

function  lastLong(str){
    str = str.trim(); //去除字符串中首尾的空格
    const arr= str.split(" ");
    return arr[arr.length-1].length;
}

24,实现lodash.get()函数

比如一个对象:{ 'a': [{ 'b': { 'c': 3 } }] },正常调用应该是
if(a.b&&a.b.c){ console.log(a.b.c)}
但是使用lodash.get可以直接调用:_.get(a.b.c)   //3

function deepGet(object, path, defaultValue) {
    return
 (!Array.isArray(path) ? path.replace(/\[/g, '.').replace(/\]/g, '').split('.') : path)
            .reduce((o, k) => (o || {})[k], object) || defaultValue;
}

25,手撸promise

class Promise{
   constructor(){
      this.status = "pending";
      this.value = undefined;
      this.err = undefined;
   }
   
   resolve(data){
      this.status = "resolve"
      this.value = data
   }

   reject(err){
      this.status = "reject"
      this.err = err
   }
 
   then(fn){
     fn(this.value);
   }

   catch(fn){
     fn(this.err);
   }
}

26,手撸Promise.all

问题1:封装一个promise,假设5S内没有返回值就丢弃这个结果
问题2:封装一个promise,解决promise.all可以返回所有的结果,而不是一个出错丢弃所有

 Promise.all = function(promises){
    const i = 0;
    let arr = [];
  let processPromise=function(data,i){
        arr[i] = data;
       if(++i==promises.length){
            resolve(arr);
        }
    }
   promises.map((item,i)=>{
     item.then((data)=>{
         processPromise(data)
        },reject)
     })
}

问题1:

const a = new Promise((resolve,reject)=>{

  const data =  $.ajax(
        url:'',
        success(data){
            resolve(data)
        }
        )

    setTimeout(function(){
        if(!data){
            reject("失败")
        }
      },5000)

    })
         

27,继承

//原型链继承
function A(){}
function B(){}
B.prototype = new A();
B.prototype.constructor = B

//构造函数继承
function A(){}
function B(val){
  A.call(this,val)
}

//组合继承
function A(){}
function B(val){
   A.call(this,val)
}
B.prototype = new A();
B.prototype.constructor = B

//寄生组合继承
function A(){}
function B(val){
  A.call(this,val)
}
B.prototype = Object.create(A.prototype)

28,实现promise.all

所有请求全部成功则调用then函数,否则调用catch,并且catch的是第一个请求错误的接口

Promise._all = (arr) => {
return new Promise((resolve, reject) => {
if (!arr.length) resolve([])
if (typeof arr[Symbol.iterator] !== 'function' || arr == null) {
throw new TypeError('arr is not iterable')
}

let len = arr.length
let count = 0;
let result = []
arr.forEach((item, index) => {
Promise.resolve(item).then((res) => {
++count
result[index] = res
if (count === len) resolve(result)
}).catch(reject)
})

})

}


// 如果一个对象有Symbol.iterator属性,并且这个属性的类型是function,那么这个对象就是可迭代的,

// 什么叫做可迭代:可以使用for...of循环,可以使用Array.from转为数组

// 有哪些可迭代对象:

29,json2dom 实现render函数

function _render(json) {

if (typeof json === 'number') {

json = String(json)

}

if (typeof json === 'string') {

return document.createTextNode(json)

}

const { tag, attrs, children } = json

const dom = document.createElement(tag)

Object.keys(attrs).forEach(key => {

dom.setAttribute(key, attrs[key])

})

children.forEach(child => {

dom.appendChildren(_render(child))

})

return dom

}


30,树形结构转列表

function tree2list(treeArr) {

const res = []

treeArr.forEach(item => {

let { children } = item

delete item.children

res.push(item)

if (children && children.length) res.push(...tree2list(children))

})

return res

}

31,列表转树形结构

// 思路解析:只需要遍历一次list表,每次都更新hashMap的属性值,由于children和hashMap属于地址引用的关系,所以更新hashMap顺便更新了children

// res = [

// {id:1,name:'hi',pid:0,children:[]}

// ]

// hashMap = {

// 1: {id:1,name:'hi',pid:0,children:[]},

// 2: {id:2,name:'hi',pid:1,children:[]},

// }

function list2tree(listArr) {

const res = []

const hashMap = {}

for (let i = 0; i < listArr.length; i++) {

const id = listArr[i].id

const pid = listArr[i].pid

// 创建新的hashMap属性

if (!hashMap[id]) {

hashMap[id] = { ...listArr[i], children: [] }

} else {

hashmap[id] = { ...arr[i], children: hashmap[id].children }

}

// 把根元素push到list

if (pid === 0) res.push(hashMap[id])

// 更新hashMap的children

if (hashMap[pid]) {

hashMap[pid].children.push(hashMap[id])

} else {

hashmap[pid] = { children: [] }

}

}

return res

}

32,实现flat数组拍平无deep

Array.prototype._flat = function () {

const arr = this

let res = []

arr.forEach(item => {

if (!Array.isArray(item)) {

res.push(item)

}else{

let newArr = item._flat()

res = res.concat(newArr)

}

})

return res

}

33,实现flat数组拍平带deep

Array.prototype._flat = function(deep){

const arr = this // this指向调用它的对象

let res = []

deep--

arr.forEach(item=>{

if(!Array.isArray(item) || deep<1){

res.push(item)

}else{

let newArr = item._flat(deep)

res = res.concat(newArr)

}

})

return res

}

34,实现instanceof

(用于判断变量是否属于数组,或者某个类的实例化对象)

// [1,2] instanceof Array

// const a = new Number(3)

// a instanceof Number ///true

function _instanceof(a,b){

if(!left)return false

return a.__proto__ === b.prototype || _instanceof(a.__proto__,b)

}

// 实例化对象.__proto__ === 构造函数.prototype

35,实现call

// 函数.call(this指向对象,参数1,参数2...),立即执行

// 函数.apply(this指向对象,[参数1,参数2...]),立即执行函数

// 函数.bind(this指向对象,参数1,参数2...)

// const obj = {

// name:'hi',

// getName:()=>{

// console.log(this.name)

// }

// }

Function.prototype._call = (obj,...param)=>{

obj = (obj===undefined || obj===null)?window:obj

obj.fn = this

const res = obj.fn(...param)

delete obj.fn

return res

}

36,实现apply

Function.prototype._apply = (obj,param)=>{

obj = (obj === undefined || obj === null)?window:obj

obj._fn = this

const res = obj._fn(...param)

delete obj._fn

return res

}

37,实现bind

Function.prototype._bind = (obj,param1)=>{

obj = (obj === undefined || obj === null)?window:obj

obj._fn = this

return function(param2){

const res = obj._fn(...[...param1,...param2])

delete obj._fn

return res

}

}

38,实现map

Array.prototype.map = (fn)=>{

const obj = this

let res =[]

for(var i=0;i<this.length;i++){

res.push(fn(obj[i],i,obj))

}

return res

}

39,实现lodash.get

function get(obj,attr){

const attrArr = attr.split('.')

let res=obj

attrArr.forEach(item=>{

res = res[item]

})

return res

}


40,实现Pick(TS)

type Pick<T,P extends keyof T>={

[K in P]:T[K]

}

41,实现Omit

type Exclude<T, U> = T extends U ? never : T; // 去除T中的U属性

type Omit<T,P extends keyof any> = Pick<T, Exclude<keyof T,P>>

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值