算法(一):全排列实现与尾递归

来源:互联网 发布:兴趣图谱源码 编辑:程序博客网 时间:2024/06/09 17:19

将n个元素按照一定的顺序排列起来,求出排列的所有组合。

算法分析, 假定n个元素的全排列组合为F(n)
1. n = 1,只有一种组合(1),即F(n) = [(1)];
2. n = k时,只需要与n = k - 1时形成的全排列组合F(k - 1)一一组合排列即可,增加的元素为 (k - 1) * F(k - 1),故现在的组合数量为 (k - 1) * F(k - 1) + F(k - 1) = k * F(k - 1);

算法复杂度,显然为n的阶乘n!。

算法实现(javascript):
1. n = 1时,返回[[1]];
2. n = k时,返回 k 与 F(k - 1)集合的排列组合;

function sequance(n) {    if(n == 1) {        //  退出递归        return [[1]]    } else {        var sn = sequance(n-1),            result = []        for(var i = 0, len = sn.length; i < len; i ++) {            for(var j = 0; j < n; j ++) {                //  复制元素                var c = sn[i].slice();                //  在数组的每个位置都插入元素                c.splice(j, 0, n)                result.push(c)            }        }        return result;    }}

尾递归实现方式如下:

/** * rs 用于保存结果 * n 用于控制深度 */function sequance(n, rs) {    if(n > 0) {        var len = rs.length,            result = [];        if(len == 0) {            result.push([n])        } else {                                for(var i = 0; i < len; i ++) {                for(var j = 0, ilen = rs[i].length; j <= ilen; j++) {                    var c = rs[i].slice();                    c.splice(j, 0, n)                    result.push(c)                }            }                           }        //  不再返回结果里进行结算,避免过多的压栈与出栈操作        return seq(n-1, result)    }    return rs}

结论

采用数组作为输出结果,在n增大时,对内存的要求会急剧增加,导致出现内存溢出错误,所以需要一种更优化的解决方案(正在思考中)。