JavaScript算法-递归的组合问题

组合问题

组合问题是指从给定个数的元素中仅仅取出指定个数的元素

  • 经典案例

从集合{a, b, c, d, e, f, g}中取出n个元素,有多少种组合实现

  • 案例分析
  • 假设取出元素为1 则有  \binom{7}{1}=7 种取法, 程序实现的话代码片段如下:
for(let i=0; i<7; i++){
    yield S[i]
}

取一个元素,我们使用一个循环,元素一个一个取出来

  • 假设要取出2个, 数学公式 \binom{7}{2}=\frac{7!}{(7-2)!2!}=21 
  • 程序实现可以是我们先取出一个,然后在一个循环从第二个开始取,然后组合起来,片段如下
for(let i=0; i<7; i++){
    for(let j=1; i<7; j++){
        yield S[i]::S[j] //把结果组合然后返回
    }
}
  • 假设要取出3个的话我们按照上面思路,可能需要三个嵌套循环

...

如果取出的球个数较多,这种思路理论成立但是很难实现,我们需要寻求更好的方式

  • 利用递归解决组合问题(n球,取k个)
  1. 把问题拆分为更小的子问题
  2. 子问题的终止条件即最小问题的解, 取出k=0或者取出k=总球数
  3. 第一种情况先取第一个球,然后在n-1个球中在取k-1个球
  4. 第二种情况直接在n-1个球中取k个
  5. 不断递归然后把解合并
  • 代码实现
function combination(S, k){
    //当设定取值个数为0或者取出k个正好等于S的长度我们返回结果
    if(k===0 || S.length===k){
        return [ S.slice(0, k) ]
    }

    //把第一个元素与剩下的元素解构出来
        const [first, ...other] = S
    //记录每次的结果
        let r = []
    //先取出一个,然后在剩下元素中取k-1个,把每次取出的都与第一个组合返回
        r = r.concat(combination(other, k-1).map(x => [first, ...x]))
    //然后在剩下的元素中取出k个
        r = r.concat(combination(other, k))
    //返回所有结果
        return r

}

 

你可能感兴趣的:(JavaScript算法)