检查在一组数字中,数字n是否等于其子集的总和

时间:2014-04-07 14:05:25

标签: php algorithm

我有一个阵列:

$permissionVals = array (1,2,4,8,16,32);

和变量

$effectivePermission = 13;

我需要以优化的方式检查此变量是否等于给定数组数组的任何子集的总和。

子集和似乎对我不起作用。 谢谢

2 个答案:

答案 0 :(得分:1)

假设$permissionVals总是包含2的幂,您可以使用位比较:

$permissionVals = array(1,2,4,8,16,32);
$target = 13;
$res = array();

foreach ($permissionVals as $val) {
    if ($target & $val) $res[] = $val;
}

if (array_sum($res) == $target)
    print_r($res);
else 
    echo 'the message you want';

在达到总和时将停止foreach循环的变体。 (如果$permissionVals很大,则很有用):

$sum = 0;
$message = 'the message you want';

foreach ($permissionVals as $val) {
    if ($target & $val) {
        $res[] = $val;
        $sum += $val;
    }
    if ($sum == $target) {
    $message = '';
    print_r($res);
    break;
    }
}

echo $message;

答案 1 :(得分:0)

感谢您的回复 我试过各种方法。终于能够让它发挥作用了:

<?php   

    $gcount = 0;

    $set = array(1,2,4,8,16,32);

    $needle = 33;
    $sum = 0;

    foreach ($set as $k => $v){
        $sum += $v;
    }

    function evaluate_array($s, $sum){
        $arr = array();
        $arr[0] = 0;

        foreach ($s as $k => $v) {
            for( $i = 0; $i <= $sum; $i++){
                if( isset($arr[$i]) ){
                    if( $arr[$i] != $v && $i + $v < $sum){
                        if( !isset($arr[$i + $v]) ){
                            $arr[$i + $v] = $v;
                        }
                    }
                }
            }
        }

        return $arr;
    }

    function solve($set, $sum, $needle){
        $stack = evaluate_array($set, $sum);

        while ($needle > 0){
            echo $stack[$needle] . "<br/>";
            $needle -= $stack[$needle];
        }
    }

    function brute_force($set, $needle){
        global $gcount;
        $gcount++;
        $sub = array(
            'found' => false
            , 'vals' => array()
            );

        $workset = $set;

        foreach($workset as $k => $v){
            if( $v == $needle){
                $sub['found'] = true;
                array_push($sub['vals'], $v);
                return $sub;
            }else{
                array_shift($workset);
                if( $needle - $v < 0){ return $sub; }
                $r = brute_force($workset, $needle - $v);
                if( $r['found'] ){
                    array_push($r['vals'], $v);
                    return $r;
                }
            }
        }

        return $sub;

    }

    function solve_bf($set, $needle){
        global $gcount;
        $sub = brute_force($set, $needle);
        $sum = 0;
        foreach($sub['vals'] as $k => $v){
            echo $v . "<br/>";
            $sum += $v;
        }

        echo "<br/>Sum: " . $sum;
        echo "<br/># Recursions: " . $gcount;
    }

    //solve($set, $sum, $needle);
    solve_bf($set, $needle);


?>

如果$ sum = 0,则不存在这样的子集。 (参考:https://github.com/burento/Subset-Sum-Problem/commit/ba549a8e67d6495fdaffafcd2e51833b7b6a57d4