或许为了自身写,或许为了知己写!

JavaScript常用算法

前言

本篇基本算法针对常用方法,无论在任何地方都有可能使用到。在这里做下笔记,偶尔拿来看看。^-^

数组去重

  • 利用对象属性不可重复特征

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

    function sort(arr) {
    var obj = {};
    var newArr = [];
    for(var i=0; i<arr.length; i++) {
    if(!obj[arr[i]]) {
    newArr.push(arr[i]);
    obj[arr[i]] = 1; // 随意赋值
    }
    }
    return newArr;
    }
  • 利用数组splice方法

1
2
3
4
5
6
7
8
9
10
11
function sort(arr) {
for(var i=0; i<arr.length; i++) {
for(var j=i+1; j<arr.length; j++) {
if(arrr[i] == arr[j]) {
arr.splice(j, 1)
j--;
}
}
}
return arr;
}
  • 利用数组indexOf方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    function sort(arr) {
    var newArr = [];
    for(var i=0; i<arr.length; i++) {
    if(newArr.indexOf(arr[i]) == -1) {
    newArr.push(arr[i])
    }
    }
    return newArr;
    }
1
2
3
4
5
6
7
8
9
function sort(arr) {
var newArr = [];
for(var i=0; i<arr.length; i++) {
if(arr.indexOf(arr[i]) == i) {
newArr.push(arr[i])
}
}
return newArr;
}
  • 使用ES6特征
1
2
3
[... new Set([1, 1, 2, 2])]
// or
Array.from(new Set([1, 1, 2, 2]))

闭包运用

输入sum(1)(2)与sum(1, 2)值相等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function sum() {
var x = arguments[0];
if(arguments.length == 1) {
return function(y) {
return x + y;
}
}else{
var x = 0;
for(var i=0; i<arguments.length; i++) {
x = x + arguments[i];
}
return x;
}
}

冒泡排序

冒泡排序是最简单的排序算法。它重复走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,即该数列已经排序完成。
思路:

  • 比较相邻的元素,如果第一个比第二个大,就交换它们。
  • 对每一个相邻元素做同样的工作,从开始第一对到结尾的最后一对,这一轮结束在最后的元素应该会是最大的数。
  • 对所有的元素重复以上步骤,除了最后一个。
  • 重复以上步骤,直到排序完成。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function sort(arr) {
var temp = '';
if(arr.length <= 1) return arr;
for(var i=0; i<arr.length-1; i++) {
for(var j=0; j<arr.length-1-i; j++) {
if(arr[j] > arr[j+1]) {
temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}

冒泡排序特征:如果数据足够大运行效率低,也比较耗时。

快速排序

基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则可分别对这两部分记录继续进行排序,达到整个序列有序。

思路:

  • 从数列中找出一个基准元素。
  • 重新排序数列,所有元素比基准元素小的排在基准元素前面,所有元素比基准元素大的排在基准元素后面(相同的数可以到任意一边),该基准元素就处于数列的中间位置。
  • 递归的把小于基准元素的子数列和大于基准元素的子数列排序。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function sort(arr) {
    if(arr.length <= 1) return arr;
    var minIndex = Math.floor(arr.length/2);
    var minVal = arr.splice(minIndex, 1);
    var left = [];
    var right = [];
    for(var i=0; i<arr.length; i++) {
    if(arr[i] < minVal) {
    left.push(arr[i])
    }else{
    right.push(arr[i])
    }
    }
    return sort(left).concat(minVal, sort(right));
    }

快速排序特征:声明两个数组,占用内存

查找字符串重复数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function filter(str) {
var obj = {};
return (function() {
for(var i=0; i<str.length; i++) {
var val = str.charAt(i);
if(obj[val] && obj[val].value == val) {
obj[val].count = ++obj[val].count;
}else{
obj[val] = {};
obj[val].count = 1;
obj[val].value = val;
}
}
return obj;
})()
}
// var str = 'aabccddd';

阶乘

需要计算n的阶乘,最多需要保存n个调用记录,复杂度O(n)。

1
2
3
4
5
6

function factorial(x) {
if(x === 1) return 1;
return x * fectorial(x - 1);
}
factorial(3) // 6

改写成尾递归(ES6函数尾调用优化部分)
只保留一个调用记录,复杂度O(1)。

1
2
3
4
5
function factorial(x, total) {
if(x === 1) return total;
return factorial(x-1, x * total);
}
factorial(3, 1) // 6

斐波那契数列

非递归实现

1
2
3
4
5
function fibonacci(x) {
if(x <= 1) return 1;
return fibonacci(x - 1) + fibonacci(x - 2);
}
fibonacci(3) // 3

改写成尾递归(ES6函数尾调用优化部分)

1
2
3
4
5
function fibonacci(x, y=1, z=1) {
if(x <= 1) return z;
return fibonacci(x-1, z, y+z);
}
fibonacci(3) // 3

字符串可以相减

1
2
3
4
5
6
7
8
9
10
11
12
var start = '2018-07-10 10:30:33';
var end = '2018-07-10 18:50:45';
function testTime(start, end) {
var now = new Date();
start = new Date(start.replace(/-/g, '-'));
end = new Date(end.replace(/-/g, '-'));
if(start - now > 0 && now - end < 0) {
return 'before';
}else{
return 'after';
}
}
———— / END / ————
0%