【前端面试】七、算法-Math、数组、数据结构等

目录

1.Math

2.数组

3.常见数据结构

4.设计模式


1.Math

  • Math.abs:求绝对值;Math.sign:判断正负,求数值符号
  • Math.ceil:向上取整; Math.floor:向下取整; Math.round:四舍五入
  • Math.max:求最大值;Math.min:求最小值
  • Math.pow:求幂;Math.sqrt:求平方根;Math.random:生成0-1之间的随机数
    // 判断素数
    const isPrime = num => {
      if(num <= 1) return false
      for(let i = 2; i <= Math.sqrt(num); i++) {
        if(num % i === 0) return false
      }
      return true
    }

    // n以内的素数
    function *sieve_primes(n) {
      let arr = Array.from({length: n - 2}, (item, index) => index + 2)
      while(arr.length > 0) {
        let prime = arr[0]
        yield prime
        arr = arr.filter(num => num % prime !== 0)
      }
    }
    const it = sieve_primes(100)
    // console.log('100以内的素数=================');
    // console.log([...it]);

2.数组

常用方法

  • Array.length:长度

  • Array.from:类数组转数组、创建数组

  • Array.isArray:是否为数组

  • Array.includes:是否包含某元素

  • Array.indexOf:获取元素序号

  • Array.concat:合并数组(元素),返回新数组

  • Array.slice:截取数组,返回新数组

  • Array.splice:删除、插入、替换,操作原数组

  • Array.push/pop/shift/unshift:入栈、出栈、出队、入队,操作原数组

  • Array.join:数组转字符串,返回字符串     

  • Array.reverse:数组反转,操作原数组

  • Array.sort:数组排序,操作原数组

  • Array.filter:创建一个新数组,筛选过滤出通过回调函数的所有元素。 

  • forEach:遍历数组,对数组的每个元素执行一次回调函数。

  • map:映射 1对1,创建一个新数组,该数组中每个元素是调用一次回调函数后的返回值。

  • reduce:累加聚合,多对1。数组中每个元素执行回调函数进行累加汇总为单个返回值。

  • Array.reduceRight:从右往左

  • Array.some:是否有满足

  • Array.every:是否全部满足

     // 数组替换
    const arr1 = [1,2,3,4,5,6,7] 
    // console.log('splice测试=================');
    // console.log(arr1.splice(2,2,'x')); // [3,4]
    // console.log(arr1); // [1,2,'x',5,6,7] 

    // console.log(arr1.splice(2,1)); // ['x']
    arr1.splice(2,0,'y')
    // console.log(arr1); // [1,2,'y',5,6,7]

    const students = [  
      {  
        id: 1,  
        name: "Alice",  
        score: 92,  
        groupId: 1,  
      },  
      {  
        id: 2,  
        name: "Bob",  
        score: 55,  
        groupId: 2,  
      },  
      {  
        id: 3,  
        name: "Charlie",  
        score: 88,  
        groupId: 1,  
      },  
      {  
        id: 4,  
        name: "David",  
        score: 76,  
        groupId: 3,  
      },  
      {  
        id: 5,  
        name: "Eva",  
        score: 62,  
        groupId: 2,  
      }  
    ];  
  
    const groups = [  
      { id: 1, name: "Math Group" },  
      { id: 2, name: "Science Group" },  
      { id: 3, name: "History Group" }  
    ];  

    // 投射
    const studentWithGrade = students.map(student => {
      return {
        ...student,
        grade: student.score >= 60 ? '及格' : '不及格'
      }
    })
    // console.log('投射测试=================');
    // console.log(studentWithGrade);

    // 过滤
    const passedStudents = students.filter(student => student.score >= 60)
    // console.log('passedStudents 测试=================');
    // console.log(passedStudents);
    const group1Students = students.filter(student => student.groupId === 1)
    // console.log('group1Students 测试=================');
    // console.log(group1Students);

    // 分组
    const studentInGroups = students.reduce((groups, student) =>{
      groups[student.groupId] = [...(groups[student.groupId] || []), student]
      return groups
    },{})
    // console.log('studentInGroups 测试=================');
    // console.log(studentInGroups);

    // 联合
    const studentWithGroupInfo = students.map(student => {
      return {
        ...student,
        groupInfo: groups.find(group => group.id === student.groupId)
      }
    })
    // console.log('studentWithGroupInfo 测试=================');
    // console.log(studentWithGroupInfo);

    // 排序 Array.prototype.sort 方法会对原数组进行排序
    const sortedByScoreAsc = students.slice().sort((a, b) => a.score - b.score);
    // console.log('sortedByScoreAsc 测试=================');
    // console.log(sortedByScoreAsc);

    const sortedByScoreDesc = students.slice().sort((a, b) => b.score - a.score);
    // console.log('sortedByScoreDesc 测试=================');
    // console.log(sortedByScoreDesc);

    const nameArr = ['张三','李四','王五'].sort((a,b) => a.localeCompare(b, 'zh'))
    // console.log('nameArr 测试=================');
    // console.log(nameArr);

数组去重

  • 使用Set:利用Set的自动去重特性,将数组转换为Set,再转换回数组。

     const unique = arr => [...new Set(arr)]
  • 使用indexOf、includes:遍历数组,检查当前元素是否已在结果数组中出现过。

  • 使用Map:利用Map对象的键是唯一的特性,遍历数组,将数组元素作为键存入Map,再从Map中获取所有键组成的数组。

笛卡尔积
 例如:[1,2] X ['a', 'b'] = [[1, 'a'], [1, 'b'], [2, 'a'], [2,'b']]

    function cartesianProduct(...Matrix) {
      if(Matrix.length ===0) return []
      if(Matrix.length === 1)return Matrix[0]

      return Matrix.reduce((A,B) => {
        const product=[]
        for(let i=0; i<A.length; i++){
          for(let j=0; j<B.length; j++){
            product.push(Array.isArray(A[i]) ? [...A[i], B[j]] : [A[i], B[j]])
          }
        }
        return product
      })
    }
    result = cartesianProduct([1, 2], ['a', 'b']);  
    console.log(result); // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]

3.常见数据结构

  集合 

  • new Set([...arr])
  • Set.add(element):添加元素
  • Set.delete(element):删除元素
  • Set.has(element):是否包含元素
  • Set.clear():清空集合
  • Set.size:集合长度
  • Set.values():返回Iterator对象
    // 子数组和整除
    // 写一个函数solve(arr, N),判断数组arr中某一项,或任意多项的和,是否被另一个整数N整除
    // 例如:solve([1,2,3,4,5], 7) => true

    // 求数组全部组合后求余数
    const solve = (arr, N) => {
      const s = new Set()
      for(let i = 0; i <= arr.length; i++) {
        for (let j = i + 1; j <= arr.length; j++) {
          const remain = arr.slice(i, j).reduce((a,b) => a + b, 0) % N
          s.add(remain)
        }
      }
      return s.has(0)
    }

    // 子问题结构思想
    const solve2 = (arr, N) => {
      const s = new Set()
      while (arr.length > 0) {
        const ak = arr.pop()
        s.add(ak)
        s.forEach(item => {
          s.add((item + ak) % N)
        })
      }
      return s.has(0)
    }

    // console.log('子数组和整除 测试=================');
    // console.log(solve2([1,2,3,4,5], 7));
    // console.log(solve2([3,9], 9));

线性表:数组、链表(单向链表、双向链表、循环链表)。

栈与队列:后进先出(LIFO)和先进先出(FIFO)的数据结构。

    // 括号匹配
    const is_balance = str => {
      const [first, ...others] = str
      const stack = [first]
      while (others.length > 0) {
        const n = others.shift()
        const c = stack[stack.length - 1]
        const ifMatch =  (c === '(' && n === ')') || (c === '[' && n === ']') || (c === '{' && n === '}')
        ifMatch ? stack.pop() : stack.push(n)
        return stack.length === 0
      }
    }

树与二叉树:二叉查找树、平衡二叉树(如AVL树、红黑树)、堆等。

:用于表示多对多关系的数据结构,包括有向图和无向图。

4.设计模式

  1. 单例模式:确保一个类仅有一个实例,并提供一个全局访问点。

  2. 工厂模式:创建对象时不直接指定具体类,而是通过调用共同的接口来指定创建哪种类的实例。

  3. 观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

Promise.all的实现

function PromiseAll(promises) {  
  return new Promise((resolve, reject) => {  
    const results = [];  
    let count = 0;  

    promises.forEach((promise, index) => {  
      Promise.resolve(promise).then(  
        value => {  
          results[index] = value;  
          if (++count === promises.length) {  
            resolve(results);  
          }  
        },  
        error => {  
          reject(error);  
        }  
      );  
    });  
  });  
}

Event Emitter的实现(简化版):

class EventEmitter {  
  constructor() {  
    this.listeners = {};  
  }  

  on(event, callback) {  
    if (!this.listeners[event]) {  
      this.listeners[event] = [];  
    }  
    this.listeners[event].push(callback);  
  }  

  emit(event, ...args) {  
    if (this.listeners[event]) {  
      this.listeners[event].forEach(callback => callback(...args));  
    }  
  }  
}

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值