javascript算法——递归

139 阅读1分钟

递归函数都有两部分: 基线 条件(base case)和递归条件(recursive case)

递归条件指的是函数调用自己,而基线条件则 指的是函数不再调用自己,从而避免形成无限循环。

1. sum

O(n)

var list = [2,4,56,32];
function sum(list){
  if(list.length){
    return list.pop() + sum(list);
  }else{
    return 0;
  }
}

var a = sum(list);

2. max

O(n)

var list = [2,4,56,32,90];
function maxNo(list,max=0){
  if(list.length){
    let curNo = list.pop();
    curNo = curNo > max ? curNo : max;
    return maxNo(list,curNo);
  }else{ 
    return max;
  }
}
var a = maxNo(list);

3. quick-sort

O(nlogn)

D&C基本步骤(divide and conquer,D&C)

(1) 找出基线条件,这种条件必须尽可能简单。

(2) 不断将问题分解(或者说缩小规模),直到符合基线条件。

var list = [9,4,56,32,90,2,3];
function quickSort(list){
  if(list.length){
    const inite =  list.shift();
    const small = [];
    const great = [];
    list.map( item => {
       item < inite ? small.push(item) : great.push(item);
    });
    return [...quickSort(small), inite, ...quickSort(great)];
  }else{
    return list;
  }
}
var a = quickSort(list);

柯里化 尾递归

// 柯里化函数
function curry (fn) {
    var _fnArgLength = fn.length;
    function wrap (...args) {
        var _args = args; // [10]
        var _argLength = _args.length;
        // 如果传的是所有参数,直接返回fn调用 10,1,0
        if (_fnArgLength === _argLength) {
            return fn.apply(null, args);
        }
        function act (...args) {
            _args = _args.concat(args); // [1]
            if (_args.length === _fnArgLength) {
              	// 递归结束
                return fn.apply(null, _args); // 10,1,0
            }
            return act; // ...递归
        }
        return act; // 2. fn(10)
    }
    return wrap; // 1. init fn
}

// 尾递归函数
function tailFactorial (num, total) {
    if (num === 1) return total;
    return tailFactorial(num - 1, num * total);
}


// 改写
var factorial = curry(tailFactorial); // return wrap;
var a = factorial(10); // return act;
a(1);    // act(1);
// 3628800;

// 等于
factorial(10,1)
// 尾递归函数
function tailFactorial (num, total,inite) {
    if (num === 1) return total+':'+inite;
    return tailFactorial(num - 1, num * total,inite+1);
}
factorial(10)(1)(2) // "3628800:11"
factorial(10,1,0)
// 柯里化
function curry(targetfn) {
  var numOfArgs = targetfn.length;
  return function fn(...rest) {
    if (rest.length < numOfArgs) {
      return fn.bind(null, ...rest);
    } else {
      return targetfn.apply(null, rest);
    }
  };
}