简单算法

  • 字符串
  • 数组
  • 正则
  • 排序
  • 递归
算法修炼什么?
  • 思维
  • 专注
  • 视野
  • 技巧

如何修炼算法?

理论知识 + 大量练习

  1. 《算法导论》,《概率》
  2. 组内分享 + 引导 + 实战

星级

数组展平简单 (零星)

展平一个数组,数组最多二维 [[1, 2], [3, 4]] => [1,2,,3,4]

arr = [[1, 2], [3, 4]]

[].concat([[1, 2], [3, 4]])
[].concat(...[[1, 2], [3, 4]])
[].apply(null, [[1, 2], [3, 4]])


function flattenOnce(arr) {
    return [].concat(...arr)
}
数组展平(递归,一星)

展平一个数组,[[1, 2], 3, [[4], 5]] => [1, 2, 3, 4, 5]
对数组S={a1, a2, ... an}, 函数F将数组展平。

image.png

function flatten(arr) {
    return [].concat(...arr.map(x => {
        Array.isArray(x) ? flatten(x) : x
    }))
}
函数截流 (一星)

过滤掉重复掉滚动事件

时序图:
image.png

function throttle(func, delay = 60) {
    let lock = false
    return (...args) => {
        if (lock) return
        func(...args)
        lock = true
        setTimeout(() => {lock = false}, delay)
    }
}

调用:

throttle(console.log)
函数节流 (一星)

过滤掉重复的验证事件(用户输入停止后300ms触发验证)

image.png

function throlle(func, delay = 300, I = null) {
    return (...args) => {
        clearInterval(I)
        I = setTimeout((...args) => func(...args), delay)
    }
}
柯里化 (二星)

对于curry(foo), g函数参数足够4个,就调用foo(a, b, c, d),如果小于4个就返回一个可继续积累参数的函数

const curr = func => {
    const g = (...allArgs) => allArgs.length >= func.length ? func(...allArgs) : (...arg) => g(...allArgs, ...args)
    return g
}

调用:

const = foo = curry((a, b, c, d) => {
    console.log(a, b, c, d)
})

foo(1)(2)(3)(4) // 1 2 3 4
foo(1)(2)(3) // 不返回
const f = foo(1)(2)(3)
f(5) // 1 2 3 5
Y-组合子(三星)

在上述柯里化函数中去掉const g?
前置lambda演算。

const y = functon (le) {
    return function (f) {
        return f(f)
    }(function (f) {
        return le(
            function (...x) {
                return (f(f)(...x))
            }
        )
    })
}

const curryY = func => y(
    g => {
        (...allArgs) => {
            allArgs.length >= func.length ? func(...allArgs) : (...args) => g(...allArgs, ...args)
        }
    }
)

const foo = curryY((a, b, c, d) => {
    console.log(a, b, c, d)
})
foo(1)(2)(3)(4)
树的编辑距离(DOM-DIFF) (四星)

将DOM抽象成一颗标签树
DOM-DIFF算法可以抽象成标签树的编辑距离

数学函数Math
  • 分页操作
  • 数组最值
  • 随机数生成
  • 素数判断

重要的Math函数

Math.abs 求绝对值
Math.ceil 向上取整
Math.floor 向下取整
Math.max 求最大数
Math.random 0~1之间的随机数
Math.sqrt 平方根
Math.sign 求数值的符号
Math.pow 求幂

分页计算:
在一个分页表格中,给定每页显示条数(pageSize)和元素的序号(index)求页码。

const pageNo = Math.ceil((index + 1) / pageSize)

pageSize = 10

0 -> 1
9 -> 1
10 -> 2
11 -> 2

数组最值:

const A = [1, 2, 4, 5, 6]
const max = Math.max(...A)

// const max = Math.max.apply(null, A)
// const max = Math.max(1, 2, 4, 5, 6)

生成20-30之间的随机整数:

Math.round(20 + Math.random() * 10)

判断一个数是否是素数:

function is_prime(n) {
    if (n <= 1) return false
    const N = Math.floor(Math.sqrt(n)) // 除平方根
    let is_prime = true
    for (let i = 2; i <= N; i++) {
        if (n % i === 0) {
            is_prime = false
            break
        }
    }
    return is_prime
}
数组和链式操作
  • JS原生的数组操作
  • 扩展库
  • 算法举例:括号匹配,子数组整除
  • SQL对应的数据处理
迭代器和Generator

Ramda

  • zip
  • converge
  • innerJoin
  • flatten
  • intersperse

leetcode

反转字符串

例如:

输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]

思路:

  1. 字符串按空格进行分割,保存数组,利用数组的反转,数组的元素的先后顺序就是单词的顺序。
  2. 对数组进行遍历,然后每个元素进行反转。

code:

let reverseString = function(s) {
    return s.split(' ').map(item => {
        return item.split('').reverse().join('')
    }).join('')
};

let reverseString = function(s) {
    return s.match(/[\w']+/g).map(item => {
        return item.split('').reverse().join('')
    }).join('')
};
计算二进制子串

计算二进制子串


alogy
1.3k 声望121 粉丝

// Designer and Developer