前端那些常见的算法

264 阅读2分钟

斐波那契数

题目

1,1,2,3,5,8,13,21...... 斐波那契数列从第三项开始,每一项都等于前两项之和。 斐波那契数列是由数学家 Leonardoda Fibonacci 以兔子繁殖为例子而提出的,所以也叫做“兔子数列”

实现

  1. 简单实现
function fio(){
   if(n===0 || n===1) {
       return 1
   }
   return fio(n-1) + fio(n-2)
}
  1. 优化实现
  const fio = (function(){
      let catr = {}
      return function(n) {
          if(catr[n] !== undefined) {
             return catr[n]
          }
          return fio[n] = (n<=2)? 1 : fio(n-1) + fio(n-2)
      }
  })()

流程理解

假如n=4时,看看递归过程的堆栈情况。

① 调用fib函数,传入参数值4。

② fib(4)=fib(3)+fib(2),需要继续调用fib(3),而fib(2)先不进入执行堆栈。

③ fib(3)=fib(2)+fib(1),需要继续调用fib(2),fib(1)先不进入执行堆栈。

④ fib(2)=fib(1)+fib(0),需要继续调用fib(1),fib(0)先不进入执行堆栈。

⑤ fib(1)返回1,停止往下调用,然后上一步的fib(0)进入堆栈。

fib(0)返回0,则 ④ 中的fib(2)=fib(1)+fib(0)=1

然后,堆栈回到③中,因为fib(3)=fib(2)+fib(1),所以将fib(1)入栈。

fib(1)返回1,则 ③ 中的fib(3)=fib(2)+fib(1)=1+1=2。

然后,堆栈回到 ② 中,因为fib(4)=fib(3)+fib(2),所以将fib(2)入栈。而fib(2)=fib(1)+fib(0),于是将fib(1)入栈。此时fib(1)直接返回1,然后继续将fib(0)入栈。则fib(2)=fib(1)+fib(0)=1,最后fib(4)=fib(3)+fib(2)=3。 图理解

二分法

通过数组折叠,找出中间值再跟需要查找的值做比较,那么会出现 min < 查找的值 < 中间值中间值 > 查找的值 > max 两种情况,继续折叠找出查找的值,他的时间复杂度是 O(logN)

解析,旋转数组

数据溢出问题 => 每次未找到目标数字时,都要修改新的查找区间,然后查找这个区间的中值,值得注意的是,(left+right)/2 这种写法在一开始是很容易溢出的,例如当left和right都是int,两个值的初始值都超过int限定大小的一半,那么left+right就会发生溢出,所以应该用left+(right-left)/2来防止求中值时候的溢出。

冒泡排序

解决传入的数组进行顺序化

function boble(arr) {
 var len = arr.length,j
 var temp;
 while(len > 1) {
    for(j = 0;j<len -1 ; j++) {
       if(arr[j] > arr[j+1]){
         temp = arr[j];
         arr[j] = arr[j+1]
         arr[j+1] = temp
       }
     }
   len-- 
 }
 return arr
}

打乱有序数组

 var arr = [1,1,2,3,4,5,6,7,8,9];
    arr.sort(function() {
        return 0.5 - Math.random()
    })
    var str = arr.join();

柯里化

柯里化定义: 是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回接受余下参数的新函数的技术。

柯里化好处: 调用函数的时候,如果某一个参数在每次调用中都相同,可以避免重复传入这个参数。

实现

单独看代码很难理解,需要自己调试一遍

function add (...args) {
//求和
    return args.reduce((a, b) => a + b)
}

function currying (fn) {
    let args = [] 
    return function temp (...newArgs) { // 通过自循环执行后面的参数
        if (newArgs.length) {
            args = [
                ...args,
                ...newArgs
            ]
            return temp
        } else {
            let val = fn.apply(this, args)
            args = [] //保证再次调用时清空
            return val
        }
    }
}

let addCurry = currying(add)
console.log(addCurry(1)(2)(3)())  //15

if(a===1 && a===2 && a===3) 成立

通过 Object.defineProperty 对数据a的监听变化

let temp = 0;
Object.defineProperty(window,'a' ,{
   get() {
     temp++
     return temp
   }
}) 
if(a===1 && a===2 && a===3) {
  console.log(true)
}

数组当中找出最小值或是最大值实现

let arrs = [1,1000,20,0,100]

//最大值
 var maxValue=Math.max.apply(Math,arrs);
// 最小值
var minValue=Math.min.apply(Math,arrs);

//具体实现
// 查找数组中最小值
function mathMin(arrs){
  var min = arrs[0];
  for(var i = 1, ilen = arrs.length; i < ilen; i+=1) {
    if(arrs[i] < min) {
      min = arrs[i];
    }
  }
  return min;
}