AnnVoV / blog

24 stars 2 forks source link

关于实现排列组合的思路 #29

Open AnnVoV opened 5 years ago

AnnVoV commented 5 years ago

去求排列组合这种的思路,其实就是用有限的元素去构造一棵树的过程,然后你把这棵树打印处理。所以我之前存在的一个错误的地方就在于我忘记了去保留树的最顶部的那个根。

看2个例子:

1.列出['b', 'a', 'o'] 三个元素可以形成的所有的排列组合字符串

bao
boa
abo
aob
oba
oab

思路: 树的根是'', 一开始子树的根是b/a/o 子树的叶子为其剩下的元素

function getArrGroup(arr) {
    let result = [];

    function createTree(root, remain) {
        if (remain.length === 0) {
            result.push(root);
            return;
        }
        for (let i = 0; i < remain.length; i++) {
            const newRoot = remain[i];
            const other = remain.slice(0, i).concat(remain.slice(i+ 1));
            createTree(root + newRoot, other);
        }
    }
    createTree('', arr);
    return result;
}
console.log(getArrGroup(['b', 'a', 'o']));

2.求给定数组的size长度的所有组合

/*
*返回arr的所有长度为size的子数组的组合
* 如arr = [1,2,3,4], size = 2
* return [[1,2], [1,3], [1,4], [2,3], [2,4], [3,4]]
*
* 再如arr = [1,2,3,4], size = 3
* return [[1,2,3], [1,2,4],[1,3,4] [2,3,4]];
*/

var a=[1,2,3,4];
function groupSplit(arr, size) {
  //TODO: 完成该函数
}
var ret = groupSplit(a, 2);
console.log(ret); // [[1,2], [1,3], [1,4], [2,3], [2,4], [3,4]]

实现思路其实和上面是一样的拉,只是退出的条件变了

function groupSplit(arr, size) {
    let result = [];

    function createTree(root, remainArr, size) {
        if (size === 0 || remainArr.length === 0) {
            result.push(root);
            return;
        }

        for (let i = 0; i <= remainArr.length - size; i++) {
            const nextRoot = remainArr[i];
            const other = remainArr.slice(i + 1);
            createTree(root.concat(nextRoot), other, size - 1);
        }
    }

    createTree([], arr, size);
    return result;
}

groupSplit([1,2,3,4], 2);