排序算法

冒泡排序

两两对比,大的放后边,最终最大的放在最末尾

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

function buble(arr) {
  if (!arr || arr.length === 0) {
    return arr;
  }
  const len = arr.length;
  for (let i = 0; i < len - 1; i++) {
    for (let j = 0; j < len - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        const k = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = k;
      }
    }
  }
  return arr
}

buble([10,4,2,3,7,5,9,8])

选择排序

每轮选出一个最小(大)值,拿一个值与剩余的其他值做对比

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

function selection(arr) {
  if (!arr || arr.length === 0) {
    return arr;
  }
  const len = arr.length;
  for (let i = 0; i < len - 1; i++) {
    for (let j = i + 1; j < len; j++) {
      if (arr[i] > arr[j]) {
        const k = arr[i];
        arr[i] = arr[j];
        arr[j] = k;
      }
    }
  }
  return arr
}

selection([10,4,2,3,7,5,9,8])

插入排序

一个值与有序列表对比,冒泡法替换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21

function insertion(arr) {
  if (!arr || arr.length === 0) {
    return arr;
  }
  const len = arr.length;
  for (let i = 1; i < len; i++) {
    for (let j = i; j > 0; j--) {
      if (arr[j] < arr[j - 1]) {
        const k = arr[j - 1];
        arr[j - 1] = arr[j];
        arr[j] = k;
      } else {
        break;
      }
    }
  }
  return arr;
}

insertion([10,4,2,3,7,5,9,8])

希尔排序

插入排序的升级版, 插入排序与选择排序结合,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22

function shellSort(arr) {
  if (!arr || arr.length === 0) {
    return arr;
  }
  let len = arr.length;
  for (let gap = Math.floor(len / 2); gap > 0; gap = Math.floor(gap / 2)) {
    for (let i = gap; i < len; i++) {
      const tmp = arr[i]
      let j = i;
      while (j >= gap && tmp < arr[j - gap]) {
                arr[j] = arr[j - gap];
                j -= gap;
            }
      arr[j] = tmp;
    }
    console.log(arr);
  }
  return arr;
}

shellSort([10,4,2,3,7,5,9,8])

其他算法

斐波那契

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

function fabonacci(n) {
  if (n <= 1) {
    return n;
  }
  let i = 0;
  let j = 1;
  while (--n) {
    j = i + j;
    i = j - i;
  }
  return j;
}

青蛙跳台阶

青蛙一次能跳一阶,也可以跳两阶,求对于N阶的台阶,有多少种跳法

对于n阶的台阶,如果青蛙第一次跳一阶,则有 f(n-1) 种跳法;如果青蛙第一次跳两阶,则有 f(n-2) 种跳法。所以一共有 f(n-1) + f(n-2) 种跳法。得出此为一个斐波那契函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15

function f(n) {
  if (n <= 2) {
    return n;
  }
  let i = 0;
  let j = 1;
  while(n--) {
    j = j + i;
    i = j - i;
  }
  return j;
}

f(100)

js类功能操作

防抖

在事件触发后单位时间执行。在单位时间内多次触发,清空定时器,重新计算

箭头函数没有this,arguments

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

function debounce(fn, delay = 500) {
  let timer;
  return function () {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(this, arguments)
      timer = null
    }, delay);
  }
} 

节流

单位时间内只执行一次

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13

function throttle(fn, delay = 500) {
  let timer;
  return function () {
    if (timer) {
      return;
    }
    timer = setTimeout(() => {
      fn.apply(this, arguments);
      timer = null;
    }, delay)
  }
}

写一个处理加法可能产生精度的函数

比如 0.1 + 0.2 = 0.3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

function checkPoint(m) {
  const a = m.toString();
  return (a.length - (a.indexOf() + 1));
}

function add(m, n) {
  const mIdx = checkPoint(m);
  const nIdx = checkPoint(n);
  const p = Math.pow(10, Math.max(mIdx, nIdx));
  return (m * p + n * p) / p
}

add(0.1, 0.123)

大数相加

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

function add(num1, num2) {
  let m = num1.length - 1;
  let n = num2.length - 1;
  const arr = [];
  let add = 0;
  for(; m >= 0 || n >= 0 || add !== 0; m--, n--) {
    const x = m >= 0 ? +num1[m] : 0;
    const y = n >= 0 ? +num2[n] : 0;
    const sum = x + y + add;
    arr.push(sum % 10);
    add = Math.floor(sum / 10);
  }
  return arr.reverse().join('');
}

add('1234567', '87654321174')

大数相乘

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

function multiply(num1, num2) {
  if (num1 === '0' || num2 === '0') {
    return '0';
  }
  const m = num1.length;
  const n = num2.length;
  const arr = Array(m + n).fill(0);
  for (let i = m - 1; i >= 0; i--) {
    const x = +num1[i];
    for (let j = n - 1; j >= 0; j--) {
      const y = +num2[j];
      const result = x * y + arr[i + j + 1];
      arr[i + j + 1] = result % 10;
      arr[i + j] += Math.floor(result / 10)
    }
  }
  while (arr[0] === 0) {
    arr.shift();
  }
  return arr.join('')
}

multiply('1234567', '87654321174')

无重复字符的最长子串

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

function lengthOfLongestSubstring(str) {
  const n = str.length;
  const last = {};
  // const last = Array(128).fill(-1);
  let start = 0;
  let len = 0;
  for (let i = 0; i < n; i++) {
    const key = str[i];
    // const key = s.charCodeAt(i);
    start = Math.max(start, (last[key] ?? -1) + 1);
    // start = Math.max(start, last[key] + 1);
    len = Math.max(len, i - start + 1);
    last[key] = i;
  }
  return len;
}

手写一个Promise all的实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

Promise.prototype.all = function (arr) {
  return arr.reduce((result, item) => {
    return item.then(value => {
      return result.then(res => {
        res.push(value)
        return res
      })
    })
  }, Promise.resolve([]))
}

Promise.prototype.all = function (arr) {
  return new Promise((resolve, reject) => {
    if (!arr) {
      reject();
    }
    if (arr.length === 0) {
      resolve([])
    }
    const result = [];
    arr.forEach((item, idx) => {
      item.then((res) => {
        result[idx] = res;
        if (result.length === arr.length) {
          resolve(result);
        }
      }).catch(err => {
        reject(err)
      })
    })
  })
}

计算数组深度

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19

function getDeep(arr) {
  const deeps = [0];
  arr.forEach((item) => {
    if (Array.isArray(item)) {
      deeps.push(getDeep(item))
    }
  })
  return Math.max(...deeps) + 1
}

function getDeep(arr) {
  return arr.reduce((deep, item) => {
    if (Array.isArray(item)) {
      return Math.max(deep, 1 + getDeep(item))
    }
    return deep;
  }, 1);
}