前端算法

1. 二分查找和冒泡排序

二分查找: 递归(分左右, 传递start,end参数)和非递归(使用while(l < h))

冒泡排序: 两个for循环

2. 快速排序

function quickSort (arr) {
  if (arr.length < 2) return arr
  var middle = Math.floor(arr.length / 2)
  var flag = arr.splice(middle, 1)[0]
  var left = [],
        right = []
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] < flag) {
      left.push(arr[i])
    } else {
      right.push(arr[i])
    }
  }
  return quickSort(left).concat([flag], quickSort(right))
}

3. 最长公共子串

function findSubStr(str1, str2) {
        if (str1.length > str2.length) {
          [str1, str2] = [str2, str1]
        }
        var result = ''
        var len = str1.length
        for (var j = len; j > 0; j--) {
          for (var i = 0; i < len - j; i++) {
            result = str1.substr(i, j)
            if (str2.includes(result)) return result
          }
        }
      }
      console.log(findSubStr('aabbcc11', 'ppooiiuubcc123'))

4. 最长公共子序列(LCS动态规划)

// dp[i][j] 计算去最大长度,记住口诀:相等左上角加一,不等取上或左最大值
function LCS(str1, str2){
        var rows =  str1.split("")
        rows.unshift("")
        var cols =  str2.split("")
        cols.unshift("")
        var m = rows.length
        var n = cols.length
        var dp = []
        for(var i = 0; i < m; i++){
            dp[i] = []
            for(var j = 0; j < n; j++){
                if(i === 0 || j === 0){
                    dp[i][j] = 0
                    continue
                }

                if(rows[i] === cols[j]){
                    dp[i][j] = dp[i-1][j-1] + 1 //对角+1
                }else{
                    dp[i][j] = Math.max( dp[i-1][j], dp[i][j-1]) //对左边,上边取最大
                }
            }
            console.log(dp[i].join(""))//调试
        }
        return dp[i-1][j-1]
    }
//!!!如果它来自左上角加一,则是子序列,否则向左或上回退。
//findValue过程,其实就是和 就是把T[i][j]的计算反过来。
// 求最长子序列
function findValue(input1,input2,n1,n2,T){
    var i = n1-1,j=n2-1;
    var result = [];//结果保存在数组中
    console.log(i);
    console.log(j);
    while(i>0 && j>0){
        if(input1[i] == input2[j]){
            result.unshift(input1[i]);
            i--;
            j--;
        }else{
            //向左或向上回退
            if(T[i-1][j]>T[i][j-1]){
                //向上回退
                i--;
            }else{
                //向左回退
                j--;
            }
        }

    }

    console.log(result);
}

5. 数组去重,多种方法

双for循环, splice剔除并i--回退

indexOf等于index

filter indexOf === index

新数组indexOf === index

使用空对象等

6. 实现一个函数功能:sum(1,2,3,4..n)转化为 sum(1)(2)(3)(4)…(n)

// 使用柯里化 + 递归
function curry ( fn ) {
  var c = (...arg) => (fn.length === arg.length) ?
          fn (...arg) : (...arg1) => c(...arg, ...arg1)
  return c
}

7. 反转二叉树

var invertTree = function (root) {
  if (root !== null) {
    [root.left, root.right] = [root.right, root.left]
    invertTree(root.left)
    invertTree(root.right)
  }
  return root
}

8. 贪心算法解决背包问题

var items = ['A','B','C','D']
var values = [50,220,60,60]
var weights = [5,20,10,12]
var capacity = 32 //背包容积

greedy(values, weights, capacity) // 320

function greedy(values, weights, capacity) {
        var result = 0
        var rest = capacity
        var sortArray = []
        var num = 0
        values.forEach((v, i) => {
          sortArray.push({
            value: v,
            weight: weights[i],
            ratio: v / weights[i]
          })
        })
        sortArray.sort((a, b) => b.ratio - a.ratio)
        sortArray.forEach((v, i) => {
          num = parseInt(rest / v.weight)
          rest -= num * v.weight
          result += num * v.value
        })
        return result
      }

9. 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

function FindNumbersWithSum(array, sum)
{
    var index = 0
    for (var i = 0; i < array.length - 1 && array[i] < sum / 2; i++) {
        for (var j = i + 1; j < array.length; j++) {
            if (array[i] + array[j] === sum) return [array[i], array[j]]
        }
        //index = array.indexOf(sum - array[i], i + 1)
       // if (index !== -1) {
       //     return [array[i], array[index]]
        //}
    }
    return []

10. 二叉树各种(层序)遍历

// 根据前序和中序重建二叉树
/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function reConstructBinaryTree(pre, vin)
{
    var result = null
    if (pre.length === 1) {
        result = {
            val: pre[0],
            left: null,
            right: null
        }
    } else if (pre.length > 1) {
        var root = pre[0]
        var vinRootIndex = vin.indexOf(root)
        var vinLeft = vin.slice(0, vinRootIndex)
        var vinRight = vin.slice(vinRootIndex + 1, vin.length)
        pre.shift()
        var preLeft = pre.slice(0, vinLeft.length)
        var preRight = pre.slice(vinLeft.length, pre.length)
        result = {
            val: root,
            left: reConstructBinaryTree(preLeft, vinLeft),
            right: reConstructBinaryTree(preRight, vinRight)
        }
    }
    return result
}

// 递归
// 前序遍历
function prevTraverse (node) {
  if (node === null) return;

  console.log(node.data);
  prevTraverse(node.left);
  prevTraverse(node.right);
}

// 中序遍历
function middleTraverse (node) {
  if (node === null) return;

  middleTraverse(node.left);
  console.log(node.data);
  middleTraverse(node.right);
}

// 后序遍历
function lastTraverse (node) {
  if (node === null) return;

  lastTraverse(node.left);
  lastTraverse(node.right);
  console.log(node.data);
}

// 非递归
// 前序遍历
function preTraverse(tree) {
        var arr = [],
          node = null
        arr.unshift(tree)
        while (arr.length) {
          node = arr.shift()
          console.log(node.root)
          if (node.right) arr.unshift(node.right)
          if (node.left) arr.unshift(node.left)
        }
      }

// 中序遍历
function middleTraverseUnRecursion (root) {
  let arr = [],
      node = root;

  while (arr.length !== 0 || node !== null) {
    if (node === null) {
      node = arr.shift();
      console.log(node.data);
      node = node.right;
    } else {
      arr.unshift(node);
      node = node.left;
    }
  }

}

// 广度优先-层序遍历
// 递归
var result = []
var stack = [tree]
var count = 0
var bfs = function () {
  var node = stack[count]
  if (node) {
    result.push(node.value)
    if (node.left) stack.push(node.left)
    if (node.right) stack.push(node.right)
    count++
    bfs()
  }
}
bfs()
console.log(result)
// 非递归
function bfs (node) {
  var result = []
  var queue = []
  queue.push(node)
  while (queue.length) {
    node = queue.shift()
    result.push(node.value)
    node.left && queue.push(node.left)
    node.right && queue.push(node.right)
  }
  return result
}

11. 各种排序

// 插入排序
function insertSort(arr) {
        var temp
        for (var i = 1; i < arr.length; i++) {
          temp = arr[i]
          for (var j = i; j > 0 && temp < arr[j - 1]; j--) {
            arr[j] = arr[j - 1]
          }
          arr[j] = temp
        }
        return arr
      }
      console.log(insertSort([3, 1, 8, 2, 5]))

// 归并排序
function mergeSort(array) {
        var result = array.slice(0)
        function sort(array) {
          var length = array.length
          var mid = Math.floor(length * 0.5)
          var left = array.slice(0, mid)
          var right = array.slice(mid, length)
          if (length === 1) return array
          return merge(sort(left), sort(right))
        }
        function merge(left, right) {
          var result = []

          while (left.length || right.length) {
            if (left.length && right.length) {
              if (left[0] < right[0]) {
                result.push(left.shift())
              } else {
                result.push(right.shift())
              }
            } else if (left.length) {
              result.push(left.shift())
            } else {
              result.push(right.shift())
            }
          }
          return result
        }
        return sort(result)
      }
      console.log(mergeSort([5, 2, 8, 3, 6]))

// 二分插入排序
function twoSort(array) {
        var len = array.length,
          i,
          j,
          tmp,
          low,
          high,
          mid,
          result
        result = array.slice(0)
        for (i = 1; i < len; i++) {
          tmp = result[i]
          low = 0
          high = i - 1
          while (low <= high) {
            mid = parseInt((high + low) / 2, 10)
            if (tmp < result[mid]) {
              high = mid - 1
            } else {
              low = mid + 1
            }
          }
          for (j = i - 1; j >= high + 1; j--) {
            result[j + 1] = result[j]
          }
          result[j + 1] = tmp
        }
        return result
      }
      console.log(twoSort([4, 1, 7, 2, 5]))

12. 使用尾递归对斐波那契优化

递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。

// 传统递归斐波那契, 会造成超时或溢出
function Fibonacci (n) {
  if ( n <= 1 ) {return 1};

  return Fibonacci(n - 1) + Fibonacci(n - 2);
}

Fibonacci(10) // 89
Fibonacci(100) // 超时
Fibonacci(500) // 超时

// 使用尾递归优化, 可规避风险
function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
  if( n <= 1 ) {return ac2};

  return Fibonacci2 (n - 1, ac2, ac1 + ac2);
}

Fibonacci2(100) // 573147844013817200000
Fibonacci2(1000) // 7.0330367711422765e+208
Fibonacci2(10000) // Infinity

13. 两个升序数组合并为一个升序数组

function sort (A, B) {
  var i = 0, j = 0, p = 0, m = A.length, n = B.length, C = []
  while (i < m || j < n) {
    if (i < m && j < n) {
      C[p++] = A[i] < B[j] ? A[i++] : B[j++]
    } else if (i < m) {
      C[p++] = A[i++]
    } else {
      C[p++] = B[j++]
    }
  }
  return C
}
原文地址:https://www.cnblogs.com/art-poet/p/12553742.html