从多个数中取出之和等于定值的组合

9 篇文章 0 订阅
5 篇文章 0 订阅

这个问题也比较常见,网上方法也很多。 这里也是用数组的方法来完成。用到了集合、子集的思想。注释中详细说明了。

从m个数中选出n个数来 ( 0 < n <= m), 要求n个数之间不能有重复,其和等于一个定值k, 求一段程序,罗列所有的可能。

如从 [11, 18, 12, 1, -2, 20, 8, 10, 7, 6] 中取出之和为18的集合,如[11,7][18]等。


<?php
header('Content-type: text/html; charset=utf-8');
/**
* 从m个数中选出n个数来 ( 0 < n <= m), 要求n个数之间不能有重复,其和等于一个定值k, 求一段程序,罗列所有的可能。
* @param int   $need 定值
* @param array $arr  选取的数组集合
* @return array      符合的子集合
*/
function sel_set($need, $arr) {    
    //子集数2的数组元素数次方
    $arr_count = count($arr);
    $set_count = pow(2, $arr_count);
    
    /**
    * 此方法原理: 对于集合{a, b, c}
    * 针对其中的元素都有2种状态1在子集中0不在
    * 0=>0 0 0 空集不需要考虑
    * 1=>0 0 1 => c 
    * 2=>0 1 0 => b
    * 3=>0 1 1 => b c
    * 4=>1 0 0 => a
    * 5=>1 0 1 => a c
    * 6=>1 1 0 => a b
    * 7=>1 1 1 => a b c 
    * 也就是将每个子集对应的编号转化为二进制 再去数组取对应元素
    */
    
    //set_arr用来存放符合需求的子集
    $set_arr = array();
    
    //set_count个子集,所以循环set_count次
    for( $i = 1; $i < $set_count; $i++ ) {
        //tmp用来存放每次子集 
        $tmp = array();
        
        //将子集对应编号转化二进制
        $dec = decbin($i);
        
        //数组集合有arr_count个元素,所以将二进制左补0为对应位,以便取数组元素
        $dec = str_pad($dec, $arr_count, 0, STR_PAD_LEFT);
        
        //对该二进制数循环 判断是否为1
        for( $j = 0; $j < $arr_count; $j++ ) {
            
            //如果当前位为1, 则将数组对应元素放入子集数组
            if( 1 == $dec[$j] ) {
                array_push($tmp, $arr[$j]);
            }
        }
        //判断当前子集之和是否等于设定的定值,符合则存入set_arr
        if( $need == array_sum($tmp) ) {
            array_push($set_arr, json_encode($tmp));
        }
    }
    
    //返回符合要求的集合
    return $set_arr;
}
//要进行选取的数组,及定值
$need = 18;
$arr = array(11, 18, 12, 1, -2, 20, 8, 10, 7, 6);

sel_set($need, $arr);


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值